net/mlx5: fix mask used for IPv6 item validation
[dpdk.git] / drivers / net / mlx5 / mlx5_flow_verbs.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2018 Mellanox Technologies, Ltd
3  */
4
5 #include <netinet/in.h>
6 #include <sys/queue.h>
7 #include <stdalign.h>
8 #include <stdint.h>
9 #include <string.h>
10
11 /* Verbs header. */
12 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
13 #ifdef PEDANTIC
14 #pragma GCC diagnostic ignored "-Wpedantic"
15 #endif
16 #include <infiniband/verbs.h>
17 #ifdef PEDANTIC
18 #pragma GCC diagnostic error "-Wpedantic"
19 #endif
20
21 #include <rte_common.h>
22 #include <rte_ether.h>
23 #include <rte_ethdev_driver.h>
24 #include <rte_flow.h>
25 #include <rte_flow_driver.h>
26 #include <rte_malloc.h>
27 #include <rte_ip.h>
28
29 #include <mlx5_glue.h>
30 #include <mlx5_prm.h>
31
32 #include "mlx5_defs.h"
33 #include "mlx5.h"
34 #include "mlx5_flow.h"
35 #include "mlx5_rxtx.h"
36
37 #define VERBS_SPEC_INNER(item_flags) \
38         (!!((item_flags) & MLX5_FLOW_LAYER_TUNNEL) ? IBV_FLOW_SPEC_INNER : 0)
39
40 /**
41  * Create Verbs flow counter with Verbs library.
42  *
43  * @param[in] dev
44  *   Pointer to the Ethernet device structure.
45  * @param[in, out] counter
46  *   mlx5 flow counter object, contains the counter id,
47  *   handle of created Verbs flow counter is returned
48  *   in cs field (if counters are supported).
49  *
50  * @return
51  *   0 On success else a negative errno value is returned
52  *   and rte_errno is set.
53  */
54 static int
55 flow_verbs_counter_create(struct rte_eth_dev *dev,
56                           struct mlx5_flow_counter *counter)
57 {
58 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
59         struct mlx5_priv *priv = dev->data->dev_private;
60         struct ibv_context *ctx = priv->sh->ctx;
61         struct ibv_counter_set_init_attr init = {
62                          .counter_set_id = counter->id};
63
64         counter->cs = mlx5_glue->create_counter_set(ctx, &init);
65         if (!counter->cs) {
66                 rte_errno = ENOTSUP;
67                 return -ENOTSUP;
68         }
69         return 0;
70 #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
71         struct mlx5_priv *priv = dev->data->dev_private;
72         struct ibv_context *ctx = priv->sh->ctx;
73         struct ibv_counters_init_attr init = {0};
74         struct ibv_counter_attach_attr attach;
75         int ret;
76
77         memset(&attach, 0, sizeof(attach));
78         counter->cs = mlx5_glue->create_counters(ctx, &init);
79         if (!counter->cs) {
80                 rte_errno = ENOTSUP;
81                 return -ENOTSUP;
82         }
83         attach.counter_desc = IBV_COUNTER_PACKETS;
84         attach.index = 0;
85         ret = mlx5_glue->attach_counters(counter->cs, &attach, NULL);
86         if (!ret) {
87                 attach.counter_desc = IBV_COUNTER_BYTES;
88                 attach.index = 1;
89                 ret = mlx5_glue->attach_counters
90                                         (counter->cs, &attach, NULL);
91         }
92         if (ret) {
93                 claim_zero(mlx5_glue->destroy_counters(counter->cs));
94                 counter->cs = NULL;
95                 rte_errno = ret;
96                 return -ret;
97         }
98         return 0;
99 #else
100         (void)dev;
101         (void)counter;
102         rte_errno = ENOTSUP;
103         return -ENOTSUP;
104 #endif
105 }
106
107 /**
108  * Get a flow counter.
109  *
110  * @param[in] dev
111  *   Pointer to the Ethernet device structure.
112  * @param[in] shared
113  *   Indicate if this counter is shared with other flows.
114  * @param[in] id
115  *   Counter identifier.
116  *
117  * @return
118  *   A pointer to the counter, NULL otherwise and rte_errno is set.
119  */
120 static struct mlx5_flow_counter *
121 flow_verbs_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id)
122 {
123         struct mlx5_priv *priv = dev->data->dev_private;
124         struct mlx5_flow_counter *cnt;
125         int ret;
126
127         if (shared) {
128                 TAILQ_FOREACH(cnt, &priv->sh->cmng.flow_counters, next) {
129                         if (cnt->shared && cnt->id == id) {
130                                 cnt->ref_cnt++;
131                                 return cnt;
132                         }
133                 }
134         }
135         cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
136         if (!cnt) {
137                 rte_errno = ENOMEM;
138                 return NULL;
139         }
140         cnt->id = id;
141         cnt->shared = shared;
142         cnt->ref_cnt = 1;
143         cnt->hits = 0;
144         cnt->bytes = 0;
145         /* Create counter with Verbs. */
146         ret = flow_verbs_counter_create(dev, cnt);
147         if (!ret) {
148                 TAILQ_INSERT_HEAD(&priv->sh->cmng.flow_counters, cnt, next);
149                 return cnt;
150         }
151         /* Some error occurred in Verbs library. */
152         rte_free(cnt);
153         rte_errno = -ret;
154         return NULL;
155 }
156
157 /**
158  * Release a flow counter.
159  *
160  * @param[in] dev
161  *   Pointer to the Ethernet device structure.
162  * @param[in] counter
163  *   Pointer to the counter handler.
164  */
165 static void
166 flow_verbs_counter_release(struct rte_eth_dev *dev,
167                            struct mlx5_flow_counter *counter)
168 {
169         struct mlx5_priv *priv = dev->data->dev_private;
170
171         if (--counter->ref_cnt == 0) {
172 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
173                 claim_zero(mlx5_glue->destroy_counter_set(counter->cs));
174 #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
175                 claim_zero(mlx5_glue->destroy_counters(counter->cs));
176 #endif
177                 TAILQ_REMOVE(&priv->sh->cmng.flow_counters, counter, next);
178                 rte_free(counter);
179         }
180 }
181
182 /**
183  * Query a flow counter via Verbs library call.
184  *
185  * @see rte_flow_query()
186  * @see rte_flow_ops
187  */
188 static int
189 flow_verbs_counter_query(struct rte_eth_dev *dev __rte_unused,
190                          struct rte_flow *flow, void *data,
191                          struct rte_flow_error *error)
192 {
193 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) || \
194         defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
195         if (flow->counter && flow->counter->cs) {
196                 struct rte_flow_query_count *qc = data;
197                 uint64_t counters[2] = {0, 0};
198 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
199                 struct ibv_query_counter_set_attr query_cs_attr = {
200                         .cs = flow->counter->cs,
201                         .query_flags = IBV_COUNTER_SET_FORCE_UPDATE,
202                 };
203                 struct ibv_counter_set_data query_out = {
204                         .out = counters,
205                         .outlen = 2 * sizeof(uint64_t),
206                 };
207                 int err = mlx5_glue->query_counter_set(&query_cs_attr,
208                                                        &query_out);
209 #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
210                 int err = mlx5_glue->query_counters
211                                (flow->counter->cs, counters,
212                                 RTE_DIM(counters),
213                                 IBV_READ_COUNTERS_ATTR_PREFER_CACHED);
214 #endif
215                 if (err)
216                         return rte_flow_error_set
217                                 (error, err,
218                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
219                                  NULL,
220                                  "cannot read counter");
221                 qc->hits_set = 1;
222                 qc->bytes_set = 1;
223                 qc->hits = counters[0] - flow->counter->hits;
224                 qc->bytes = counters[1] - flow->counter->bytes;
225                 if (qc->reset) {
226                         flow->counter->hits = counters[0];
227                         flow->counter->bytes = counters[1];
228                 }
229                 return 0;
230         }
231         return rte_flow_error_set(error, EINVAL,
232                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
233                                   NULL,
234                                   "flow does not have counter");
235 #else
236         (void)flow;
237         (void)data;
238         return rte_flow_error_set(error, ENOTSUP,
239                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
240                                   NULL,
241                                   "counters are not available");
242 #endif
243 }
244
245 /**
246  * Add a verbs item specification into @p verbs.
247  *
248  * @param[out] verbs
249  *   Pointer to verbs structure.
250  * @param[in] src
251  *   Create specification.
252  * @param[in] size
253  *   Size in bytes of the specification to copy.
254  */
255 static void
256 flow_verbs_spec_add(struct mlx5_flow_verbs *verbs, void *src, unsigned int size)
257 {
258         void *dst;
259
260         if (!verbs)
261                 return;
262         MLX5_ASSERT(verbs->specs);
263         dst = (void *)(verbs->specs + verbs->size);
264         memcpy(dst, src, size);
265         ++verbs->attr->num_of_specs;
266         verbs->size += size;
267 }
268
269 /**
270  * Convert the @p item into a Verbs specification. This function assumes that
271  * the input is valid and that there is space to insert the requested item
272  * into the flow.
273  *
274  * @param[in, out] dev_flow
275  *   Pointer to dev_flow structure.
276  * @param[in] item
277  *   Item specification.
278  * @param[in] item_flags
279  *   Parsed item flags.
280  */
281 static void
282 flow_verbs_translate_item_eth(struct mlx5_flow *dev_flow,
283                               const struct rte_flow_item *item,
284                               uint64_t item_flags)
285 {
286         const struct rte_flow_item_eth *spec = item->spec;
287         const struct rte_flow_item_eth *mask = item->mask;
288         const unsigned int size = sizeof(struct ibv_flow_spec_eth);
289         struct ibv_flow_spec_eth eth = {
290                 .type = IBV_FLOW_SPEC_ETH | VERBS_SPEC_INNER(item_flags),
291                 .size = size,
292         };
293
294         if (!mask)
295                 mask = &rte_flow_item_eth_mask;
296         if (spec) {
297                 unsigned int i;
298
299                 memcpy(&eth.val.dst_mac, spec->dst.addr_bytes,
300                         RTE_ETHER_ADDR_LEN);
301                 memcpy(&eth.val.src_mac, spec->src.addr_bytes,
302                         RTE_ETHER_ADDR_LEN);
303                 eth.val.ether_type = spec->type;
304                 memcpy(&eth.mask.dst_mac, mask->dst.addr_bytes,
305                         RTE_ETHER_ADDR_LEN);
306                 memcpy(&eth.mask.src_mac, mask->src.addr_bytes,
307                         RTE_ETHER_ADDR_LEN);
308                 eth.mask.ether_type = mask->type;
309                 /* Remove unwanted bits from values. */
310                 for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i) {
311                         eth.val.dst_mac[i] &= eth.mask.dst_mac[i];
312                         eth.val.src_mac[i] &= eth.mask.src_mac[i];
313                 }
314                 eth.val.ether_type &= eth.mask.ether_type;
315         }
316         flow_verbs_spec_add(&dev_flow->verbs, &eth, size);
317 }
318
319 /**
320  * Update the VLAN tag in the Verbs Ethernet specification.
321  * This function assumes that the input is valid and there is space to add
322  * the requested item.
323  *
324  * @param[in, out] attr
325  *   Pointer to Verbs attributes structure.
326  * @param[in] eth
327  *   Verbs structure containing the VLAN information to copy.
328  */
329 static void
330 flow_verbs_item_vlan_update(struct ibv_flow_attr *attr,
331                             struct ibv_flow_spec_eth *eth)
332 {
333         unsigned int i;
334         const enum ibv_flow_spec_type search = eth->type;
335         struct ibv_spec_header *hdr = (struct ibv_spec_header *)
336                 ((uint8_t *)attr + sizeof(struct ibv_flow_attr));
337
338         for (i = 0; i != attr->num_of_specs; ++i) {
339                 if (hdr->type == search) {
340                         struct ibv_flow_spec_eth *e =
341                                 (struct ibv_flow_spec_eth *)hdr;
342
343                         e->val.vlan_tag = eth->val.vlan_tag;
344                         e->mask.vlan_tag = eth->mask.vlan_tag;
345                         e->val.ether_type = eth->val.ether_type;
346                         e->mask.ether_type = eth->mask.ether_type;
347                         break;
348                 }
349                 hdr = (struct ibv_spec_header *)((uint8_t *)hdr + hdr->size);
350         }
351 }
352
353 /**
354  * Convert the @p item into a Verbs specification. This function assumes that
355  * the input is valid and that there is space to insert the requested item
356  * into the flow.
357  *
358  * @param[in, out] dev_flow
359  *   Pointer to dev_flow structure.
360  * @param[in] item
361  *   Item specification.
362  * @param[in] item_flags
363  *   Parsed item flags.
364  */
365 static void
366 flow_verbs_translate_item_vlan(struct mlx5_flow *dev_flow,
367                                const struct rte_flow_item *item,
368                                uint64_t item_flags)
369 {
370         const struct rte_flow_item_vlan *spec = item->spec;
371         const struct rte_flow_item_vlan *mask = item->mask;
372         unsigned int size = sizeof(struct ibv_flow_spec_eth);
373         const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
374         struct ibv_flow_spec_eth eth = {
375                 .type = IBV_FLOW_SPEC_ETH | VERBS_SPEC_INNER(item_flags),
376                 .size = size,
377         };
378         const uint32_t l2m = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
379                                       MLX5_FLOW_LAYER_OUTER_L2;
380
381         if (!mask)
382                 mask = &rte_flow_item_vlan_mask;
383         if (spec) {
384                 eth.val.vlan_tag = spec->tci;
385                 eth.mask.vlan_tag = mask->tci;
386                 eth.val.vlan_tag &= eth.mask.vlan_tag;
387                 eth.val.ether_type = spec->inner_type;
388                 eth.mask.ether_type = mask->inner_type;
389                 eth.val.ether_type &= eth.mask.ether_type;
390         }
391         if (!(item_flags & l2m))
392                 flow_verbs_spec_add(&dev_flow->verbs, &eth, size);
393         else
394                 flow_verbs_item_vlan_update(dev_flow->verbs.attr, &eth);
395         if (!tunnel)
396                 dev_flow->verbs.vf_vlan.tag =
397                         rte_be_to_cpu_16(spec->tci) & 0x0fff;
398 }
399
400 /**
401  * Convert the @p item into a Verbs specification. This function assumes that
402  * the input is valid and that there is space to insert the requested item
403  * into the flow.
404  *
405  * @param[in, out] dev_flow
406  *   Pointer to dev_flow structure.
407  * @param[in] item
408  *   Item specification.
409  * @param[in] item_flags
410  *   Parsed item flags.
411  */
412 static void
413 flow_verbs_translate_item_ipv4(struct mlx5_flow *dev_flow,
414                                const struct rte_flow_item *item,
415                                uint64_t item_flags)
416 {
417         const struct rte_flow_item_ipv4 *spec = item->spec;
418         const struct rte_flow_item_ipv4 *mask = item->mask;
419         unsigned int size = sizeof(struct ibv_flow_spec_ipv4_ext);
420         struct ibv_flow_spec_ipv4_ext ipv4 = {
421                 .type = IBV_FLOW_SPEC_IPV4_EXT | VERBS_SPEC_INNER(item_flags),
422                 .size = size,
423         };
424
425         if (!mask)
426                 mask = &rte_flow_item_ipv4_mask;
427         if (spec) {
428                 ipv4.val = (struct ibv_flow_ipv4_ext_filter){
429                         .src_ip = spec->hdr.src_addr,
430                         .dst_ip = spec->hdr.dst_addr,
431                         .proto = spec->hdr.next_proto_id,
432                         .tos = spec->hdr.type_of_service,
433                 };
434                 ipv4.mask = (struct ibv_flow_ipv4_ext_filter){
435                         .src_ip = mask->hdr.src_addr,
436                         .dst_ip = mask->hdr.dst_addr,
437                         .proto = mask->hdr.next_proto_id,
438                         .tos = mask->hdr.type_of_service,
439                 };
440                 /* Remove unwanted bits from values. */
441                 ipv4.val.src_ip &= ipv4.mask.src_ip;
442                 ipv4.val.dst_ip &= ipv4.mask.dst_ip;
443                 ipv4.val.proto &= ipv4.mask.proto;
444                 ipv4.val.tos &= ipv4.mask.tos;
445         }
446         flow_verbs_spec_add(&dev_flow->verbs, &ipv4, size);
447 }
448
449 /**
450  * Convert the @p item into a Verbs specification. This function assumes that
451  * the input is valid and that there is space to insert the requested item
452  * into the flow.
453  *
454  * @param[in, out] dev_flow
455  *   Pointer to dev_flow structure.
456  * @param[in] item
457  *   Item specification.
458  * @param[in] item_flags
459  *   Parsed item flags.
460  */
461 static void
462 flow_verbs_translate_item_ipv6(struct mlx5_flow *dev_flow,
463                                const struct rte_flow_item *item,
464                                uint64_t item_flags)
465 {
466         const struct rte_flow_item_ipv6 *spec = item->spec;
467         const struct rte_flow_item_ipv6 *mask = item->mask;
468         unsigned int size = sizeof(struct ibv_flow_spec_ipv6);
469         struct ibv_flow_spec_ipv6 ipv6 = {
470                 .type = IBV_FLOW_SPEC_IPV6 | VERBS_SPEC_INNER(item_flags),
471                 .size = size,
472         };
473
474         if (!mask)
475                 mask = &rte_flow_item_ipv6_mask;
476         if (spec) {
477                 unsigned int i;
478                 uint32_t vtc_flow_val;
479                 uint32_t vtc_flow_mask;
480
481                 memcpy(&ipv6.val.src_ip, spec->hdr.src_addr,
482                        RTE_DIM(ipv6.val.src_ip));
483                 memcpy(&ipv6.val.dst_ip, spec->hdr.dst_addr,
484                        RTE_DIM(ipv6.val.dst_ip));
485                 memcpy(&ipv6.mask.src_ip, mask->hdr.src_addr,
486                        RTE_DIM(ipv6.mask.src_ip));
487                 memcpy(&ipv6.mask.dst_ip, mask->hdr.dst_addr,
488                        RTE_DIM(ipv6.mask.dst_ip));
489                 vtc_flow_val = rte_be_to_cpu_32(spec->hdr.vtc_flow);
490                 vtc_flow_mask = rte_be_to_cpu_32(mask->hdr.vtc_flow);
491                 ipv6.val.flow_label =
492                         rte_cpu_to_be_32((vtc_flow_val & RTE_IPV6_HDR_FL_MASK) >>
493                                          RTE_IPV6_HDR_FL_SHIFT);
494                 ipv6.val.traffic_class = (vtc_flow_val & RTE_IPV6_HDR_TC_MASK) >>
495                                          RTE_IPV6_HDR_TC_SHIFT;
496                 ipv6.val.next_hdr = spec->hdr.proto;
497                 ipv6.mask.flow_label =
498                         rte_cpu_to_be_32((vtc_flow_mask & RTE_IPV6_HDR_FL_MASK) >>
499                                          RTE_IPV6_HDR_FL_SHIFT);
500                 ipv6.mask.traffic_class = (vtc_flow_mask & RTE_IPV6_HDR_TC_MASK) >>
501                                           RTE_IPV6_HDR_TC_SHIFT;
502                 ipv6.mask.next_hdr = mask->hdr.proto;
503                 /* Remove unwanted bits from values. */
504                 for (i = 0; i < RTE_DIM(ipv6.val.src_ip); ++i) {
505                         ipv6.val.src_ip[i] &= ipv6.mask.src_ip[i];
506                         ipv6.val.dst_ip[i] &= ipv6.mask.dst_ip[i];
507                 }
508                 ipv6.val.flow_label &= ipv6.mask.flow_label;
509                 ipv6.val.traffic_class &= ipv6.mask.traffic_class;
510                 ipv6.val.next_hdr &= ipv6.mask.next_hdr;
511         }
512         flow_verbs_spec_add(&dev_flow->verbs, &ipv6, size);
513 }
514
515 /**
516  * Convert the @p item into a Verbs specification. This function assumes that
517  * the input is valid and that there is space to insert the requested item
518  * into the flow.
519  *
520  * @param[in, out] dev_flow
521  *   Pointer to dev_flow structure.
522  * @param[in] item
523  *   Item specification.
524  * @param[in] item_flags
525  *   Parsed item flags.
526  */
527 static void
528 flow_verbs_translate_item_tcp(struct mlx5_flow *dev_flow,
529                               const struct rte_flow_item *item,
530                               uint64_t item_flags __rte_unused)
531 {
532         const struct rte_flow_item_tcp *spec = item->spec;
533         const struct rte_flow_item_tcp *mask = item->mask;
534         unsigned int size = sizeof(struct ibv_flow_spec_tcp_udp);
535         struct ibv_flow_spec_tcp_udp tcp = {
536                 .type = IBV_FLOW_SPEC_TCP | VERBS_SPEC_INNER(item_flags),
537                 .size = size,
538         };
539
540         if (!mask)
541                 mask = &rte_flow_item_tcp_mask;
542         if (spec) {
543                 tcp.val.dst_port = spec->hdr.dst_port;
544                 tcp.val.src_port = spec->hdr.src_port;
545                 tcp.mask.dst_port = mask->hdr.dst_port;
546                 tcp.mask.src_port = mask->hdr.src_port;
547                 /* Remove unwanted bits from values. */
548                 tcp.val.src_port &= tcp.mask.src_port;
549                 tcp.val.dst_port &= tcp.mask.dst_port;
550         }
551         flow_verbs_spec_add(&dev_flow->verbs, &tcp, size);
552 }
553
554 /**
555  * Convert the @p item into a Verbs specification. This function assumes that
556  * the input is valid and that there is space to insert the requested item
557  * into the flow.
558  *
559  * @param[in, out] dev_flow
560  *   Pointer to dev_flow structure.
561  * @param[in] item
562  *   Item specification.
563  * @param[in] item_flags
564  *   Parsed item flags.
565  */
566 static void
567 flow_verbs_translate_item_udp(struct mlx5_flow *dev_flow,
568                               const struct rte_flow_item *item,
569                               uint64_t item_flags __rte_unused)
570 {
571         const struct rte_flow_item_udp *spec = item->spec;
572         const struct rte_flow_item_udp *mask = item->mask;
573         unsigned int size = sizeof(struct ibv_flow_spec_tcp_udp);
574         struct ibv_flow_spec_tcp_udp udp = {
575                 .type = IBV_FLOW_SPEC_UDP | VERBS_SPEC_INNER(item_flags),
576                 .size = size,
577         };
578
579         if (!mask)
580                 mask = &rte_flow_item_udp_mask;
581         if (spec) {
582                 udp.val.dst_port = spec->hdr.dst_port;
583                 udp.val.src_port = spec->hdr.src_port;
584                 udp.mask.dst_port = mask->hdr.dst_port;
585                 udp.mask.src_port = mask->hdr.src_port;
586                 /* Remove unwanted bits from values. */
587                 udp.val.src_port &= udp.mask.src_port;
588                 udp.val.dst_port &= udp.mask.dst_port;
589         }
590         flow_verbs_spec_add(&dev_flow->verbs, &udp, size);
591 }
592
593 /**
594  * Convert the @p item into a Verbs specification. This function assumes that
595  * the input is valid and that there is space to insert the requested item
596  * into the flow.
597  *
598  * @param[in, out] dev_flow
599  *   Pointer to dev_flow structure.
600  * @param[in] item
601  *   Item specification.
602  * @param[in] item_flags
603  *   Parsed item flags.
604  */
605 static void
606 flow_verbs_translate_item_vxlan(struct mlx5_flow *dev_flow,
607                                 const struct rte_flow_item *item,
608                                 uint64_t item_flags __rte_unused)
609 {
610         const struct rte_flow_item_vxlan *spec = item->spec;
611         const struct rte_flow_item_vxlan *mask = item->mask;
612         unsigned int size = sizeof(struct ibv_flow_spec_tunnel);
613         struct ibv_flow_spec_tunnel vxlan = {
614                 .type = IBV_FLOW_SPEC_VXLAN_TUNNEL,
615                 .size = size,
616         };
617         union vni {
618                 uint32_t vlan_id;
619                 uint8_t vni[4];
620         } id = { .vlan_id = 0, };
621
622         if (!mask)
623                 mask = &rte_flow_item_vxlan_mask;
624         if (spec) {
625                 memcpy(&id.vni[1], spec->vni, 3);
626                 vxlan.val.tunnel_id = id.vlan_id;
627                 memcpy(&id.vni[1], mask->vni, 3);
628                 vxlan.mask.tunnel_id = id.vlan_id;
629                 /* Remove unwanted bits from values. */
630                 vxlan.val.tunnel_id &= vxlan.mask.tunnel_id;
631         }
632         flow_verbs_spec_add(&dev_flow->verbs, &vxlan, size);
633 }
634
635 /**
636  * Convert the @p item into a Verbs specification. This function assumes that
637  * the input is valid and that there is space to insert the requested item
638  * into the flow.
639  *
640  * @param[in, out] dev_flow
641  *   Pointer to dev_flow structure.
642  * @param[in] item
643  *   Item specification.
644  * @param[in] item_flags
645  *   Parsed item flags.
646  */
647 static void
648 flow_verbs_translate_item_vxlan_gpe(struct mlx5_flow *dev_flow,
649                                     const struct rte_flow_item *item,
650                                     uint64_t item_flags __rte_unused)
651 {
652         const struct rte_flow_item_vxlan_gpe *spec = item->spec;
653         const struct rte_flow_item_vxlan_gpe *mask = item->mask;
654         unsigned int size = sizeof(struct ibv_flow_spec_tunnel);
655         struct ibv_flow_spec_tunnel vxlan_gpe = {
656                 .type = IBV_FLOW_SPEC_VXLAN_TUNNEL,
657                 .size = size,
658         };
659         union vni {
660                 uint32_t vlan_id;
661                 uint8_t vni[4];
662         } id = { .vlan_id = 0, };
663
664         if (!mask)
665                 mask = &rte_flow_item_vxlan_gpe_mask;
666         if (spec) {
667                 memcpy(&id.vni[1], spec->vni, 3);
668                 vxlan_gpe.val.tunnel_id = id.vlan_id;
669                 memcpy(&id.vni[1], mask->vni, 3);
670                 vxlan_gpe.mask.tunnel_id = id.vlan_id;
671                 /* Remove unwanted bits from values. */
672                 vxlan_gpe.val.tunnel_id &= vxlan_gpe.mask.tunnel_id;
673         }
674         flow_verbs_spec_add(&dev_flow->verbs, &vxlan_gpe, size);
675 }
676
677 /**
678  * Update the protocol in Verbs IPv4/IPv6 spec.
679  *
680  * @param[in, out] attr
681  *   Pointer to Verbs attributes structure.
682  * @param[in] search
683  *   Specification type to search in order to update the IP protocol.
684  * @param[in] protocol
685  *   Protocol value to set if none is present in the specification.
686  */
687 static void
688 flow_verbs_item_gre_ip_protocol_update(struct ibv_flow_attr *attr,
689                                        enum ibv_flow_spec_type search,
690                                        uint8_t protocol)
691 {
692         unsigned int i;
693         struct ibv_spec_header *hdr = (struct ibv_spec_header *)
694                 ((uint8_t *)attr + sizeof(struct ibv_flow_attr));
695
696         if (!attr)
697                 return;
698         for (i = 0; i != attr->num_of_specs; ++i) {
699                 if (hdr->type == search) {
700                         union {
701                                 struct ibv_flow_spec_ipv4_ext *ipv4;
702                                 struct ibv_flow_spec_ipv6 *ipv6;
703                         } ip;
704
705                         switch (search) {
706                         case IBV_FLOW_SPEC_IPV4_EXT:
707                                 ip.ipv4 = (struct ibv_flow_spec_ipv4_ext *)hdr;
708                                 if (!ip.ipv4->val.proto) {
709                                         ip.ipv4->val.proto = protocol;
710                                         ip.ipv4->mask.proto = 0xff;
711                                 }
712                                 break;
713                         case IBV_FLOW_SPEC_IPV6:
714                                 ip.ipv6 = (struct ibv_flow_spec_ipv6 *)hdr;
715                                 if (!ip.ipv6->val.next_hdr) {
716                                         ip.ipv6->val.next_hdr = protocol;
717                                         ip.ipv6->mask.next_hdr = 0xff;
718                                 }
719                                 break;
720                         default:
721                                 break;
722                         }
723                         break;
724                 }
725                 hdr = (struct ibv_spec_header *)((uint8_t *)hdr + hdr->size);
726         }
727 }
728
729 /**
730  * Convert the @p item into a Verbs specification. This function assumes that
731  * the input is valid and that there is space to insert the requested item
732  * into the flow.
733  *
734  * @param[in, out] dev_flow
735  *   Pointer to dev_flow structure.
736  * @param[in] item
737  *   Item specification.
738  * @param[in] item_flags
739  *   Parsed item flags.
740  */
741 static void
742 flow_verbs_translate_item_gre(struct mlx5_flow *dev_flow,
743                               const struct rte_flow_item *item __rte_unused,
744                               uint64_t item_flags)
745 {
746         struct mlx5_flow_verbs *verbs = &dev_flow->verbs;
747 #ifndef HAVE_IBV_DEVICE_MPLS_SUPPORT
748         unsigned int size = sizeof(struct ibv_flow_spec_tunnel);
749         struct ibv_flow_spec_tunnel tunnel = {
750                 .type = IBV_FLOW_SPEC_VXLAN_TUNNEL,
751                 .size = size,
752         };
753 #else
754         const struct rte_flow_item_gre *spec = item->spec;
755         const struct rte_flow_item_gre *mask = item->mask;
756         unsigned int size = sizeof(struct ibv_flow_spec_gre);
757         struct ibv_flow_spec_gre tunnel = {
758                 .type = IBV_FLOW_SPEC_GRE,
759                 .size = size,
760         };
761
762         if (!mask)
763                 mask = &rte_flow_item_gre_mask;
764         if (spec) {
765                 tunnel.val.c_ks_res0_ver = spec->c_rsvd0_ver;
766                 tunnel.val.protocol = spec->protocol;
767                 tunnel.mask.c_ks_res0_ver = mask->c_rsvd0_ver;
768                 tunnel.mask.protocol = mask->protocol;
769                 /* Remove unwanted bits from values. */
770                 tunnel.val.c_ks_res0_ver &= tunnel.mask.c_ks_res0_ver;
771                 tunnel.val.protocol &= tunnel.mask.protocol;
772                 tunnel.val.key &= tunnel.mask.key;
773         }
774 #endif
775         if (item_flags & MLX5_FLOW_LAYER_OUTER_L3_IPV4)
776                 flow_verbs_item_gre_ip_protocol_update(verbs->attr,
777                                                        IBV_FLOW_SPEC_IPV4_EXT,
778                                                        IPPROTO_GRE);
779         else
780                 flow_verbs_item_gre_ip_protocol_update(verbs->attr,
781                                                        IBV_FLOW_SPEC_IPV6,
782                                                        IPPROTO_GRE);
783         flow_verbs_spec_add(verbs, &tunnel, size);
784 }
785
786 /**
787  * Convert the @p action into a Verbs specification. This function assumes that
788  * the input is valid and that there is space to insert the requested action
789  * into the flow. This function also return the action that was added.
790  *
791  * @param[in, out] dev_flow
792  *   Pointer to dev_flow structure.
793  * @param[in] item
794  *   Item specification.
795  * @param[in] item_flags
796  *   Parsed item flags.
797  */
798 static void
799 flow_verbs_translate_item_mpls(struct mlx5_flow *dev_flow __rte_unused,
800                                const struct rte_flow_item *item __rte_unused,
801                                uint64_t item_flags __rte_unused)
802 {
803 #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT
804         const struct rte_flow_item_mpls *spec = item->spec;
805         const struct rte_flow_item_mpls *mask = item->mask;
806         unsigned int size = sizeof(struct ibv_flow_spec_mpls);
807         struct ibv_flow_spec_mpls mpls = {
808                 .type = IBV_FLOW_SPEC_MPLS,
809                 .size = size,
810         };
811
812         if (!mask)
813                 mask = &rte_flow_item_mpls_mask;
814         if (spec) {
815                 memcpy(&mpls.val.label, spec, sizeof(mpls.val.label));
816                 memcpy(&mpls.mask.label, mask, sizeof(mpls.mask.label));
817                 /* Remove unwanted bits from values.  */
818                 mpls.val.label &= mpls.mask.label;
819         }
820         flow_verbs_spec_add(&dev_flow->verbs, &mpls, size);
821 #endif
822 }
823
824 /**
825  * Convert the @p action into a Verbs specification. This function assumes that
826  * the input is valid and that there is space to insert the requested action
827  * into the flow.
828  *
829  * @param[in] dev_flow
830  *   Pointer to mlx5_flow.
831  * @param[in] action
832  *   Action configuration.
833  */
834 static void
835 flow_verbs_translate_action_drop
836         (struct mlx5_flow *dev_flow,
837          const struct rte_flow_action *action __rte_unused)
838 {
839         unsigned int size = sizeof(struct ibv_flow_spec_action_drop);
840         struct ibv_flow_spec_action_drop drop = {
841                         .type = IBV_FLOW_SPEC_ACTION_DROP,
842                         .size = size,
843         };
844
845         flow_verbs_spec_add(&dev_flow->verbs, &drop, size);
846 }
847
848 /**
849  * Convert the @p action into a Verbs specification. This function assumes that
850  * the input is valid and that there is space to insert the requested action
851  * into the flow.
852  *
853  * @param[in] dev_flow
854  *   Pointer to mlx5_flow.
855  * @param[in] action
856  *   Action configuration.
857  */
858 static void
859 flow_verbs_translate_action_queue(struct mlx5_flow *dev_flow,
860                                   const struct rte_flow_action *action)
861 {
862         const struct rte_flow_action_queue *queue = action->conf;
863         struct rte_flow *flow = dev_flow->flow;
864
865         if (flow->rss.queue)
866                 (*flow->rss.queue)[0] = queue->index;
867         flow->rss.queue_num = 1;
868 }
869
870 /**
871  * Convert the @p action into a Verbs specification. This function assumes that
872  * the input is valid and that there is space to insert the requested action
873  * into the flow.
874  *
875  * @param[in] action
876  *   Action configuration.
877  * @param[in, out] action_flags
878  *   Pointer to the detected actions.
879  * @param[in] dev_flow
880  *   Pointer to mlx5_flow.
881  */
882 static void
883 flow_verbs_translate_action_rss(struct mlx5_flow *dev_flow,
884                                 const struct rte_flow_action *action)
885 {
886         const struct rte_flow_action_rss *rss = action->conf;
887         const uint8_t *rss_key;
888         struct rte_flow *flow = dev_flow->flow;
889
890         if (flow->rss.queue)
891                 memcpy((*flow->rss.queue), rss->queue,
892                        rss->queue_num * sizeof(uint16_t));
893         flow->rss.queue_num = rss->queue_num;
894         /* NULL RSS key indicates default RSS key. */
895         rss_key = !rss->key ? rss_hash_default_key : rss->key;
896         memcpy(flow->rss.key, rss_key, MLX5_RSS_HASH_KEY_LEN);
897         /*
898          * rss->level and rss.types should be set in advance when expanding
899          * items for RSS.
900          */
901 }
902
903 /**
904  * Convert the @p action into a Verbs specification. This function assumes that
905  * the input is valid and that there is space to insert the requested action
906  * into the flow.
907  *
908  * @param[in] dev_flow
909  *   Pointer to mlx5_flow.
910  * @param[in] action
911  *   Action configuration.
912  */
913 static void
914 flow_verbs_translate_action_flag
915         (struct mlx5_flow *dev_flow,
916          const struct rte_flow_action *action __rte_unused)
917 {
918         unsigned int size = sizeof(struct ibv_flow_spec_action_tag);
919         struct ibv_flow_spec_action_tag tag = {
920                 .type = IBV_FLOW_SPEC_ACTION_TAG,
921                 .size = size,
922                 .tag_id = mlx5_flow_mark_set(MLX5_FLOW_MARK_DEFAULT),
923         };
924
925         flow_verbs_spec_add(&dev_flow->verbs, &tag, size);
926 }
927
928 /**
929  * Convert the @p action into a Verbs specification. This function assumes that
930  * the input is valid and that there is space to insert the requested action
931  * into the flow.
932  *
933  * @param[in] dev_flow
934  *   Pointer to mlx5_flow.
935  * @param[in] action
936  *   Action configuration.
937  */
938 static void
939 flow_verbs_translate_action_mark(struct mlx5_flow *dev_flow,
940                                  const struct rte_flow_action *action)
941 {
942         const struct rte_flow_action_mark *mark = action->conf;
943         unsigned int size = sizeof(struct ibv_flow_spec_action_tag);
944         struct ibv_flow_spec_action_tag tag = {
945                 .type = IBV_FLOW_SPEC_ACTION_TAG,
946                 .size = size,
947                 .tag_id = mlx5_flow_mark_set(mark->id),
948         };
949
950         flow_verbs_spec_add(&dev_flow->verbs, &tag, size);
951 }
952
953 /**
954  * Convert the @p action into a Verbs specification. This function assumes that
955  * the input is valid and that there is space to insert the requested action
956  * into the flow.
957  *
958  * @param[in] dev
959  *   Pointer to the Ethernet device structure.
960  * @param[in] action
961  *   Action configuration.
962  * @param[in] dev_flow
963  *   Pointer to mlx5_flow.
964  * @param[out] error
965  *   Pointer to error structure.
966  *
967  * @return
968  *   0 On success else a negative errno value is returned and rte_errno is set.
969  */
970 static int
971 flow_verbs_translate_action_count(struct mlx5_flow *dev_flow,
972                                   const struct rte_flow_action *action,
973                                   struct rte_eth_dev *dev,
974                                   struct rte_flow_error *error)
975 {
976         const struct rte_flow_action_count *count = action->conf;
977         struct rte_flow *flow = dev_flow->flow;
978 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) || \
979         defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
980         unsigned int size = sizeof(struct ibv_flow_spec_counter_action);
981         struct ibv_flow_spec_counter_action counter = {
982                 .type = IBV_FLOW_SPEC_ACTION_COUNT,
983                 .size = size,
984         };
985 #endif
986
987         if (!flow->counter) {
988                 flow->counter = flow_verbs_counter_new(dev, count->shared,
989                                                        count->id);
990                 if (!flow->counter)
991                         return rte_flow_error_set(error, rte_errno,
992                                                   RTE_FLOW_ERROR_TYPE_ACTION,
993                                                   action,
994                                                   "cannot get counter"
995                                                   " context.");
996         }
997 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
998         counter.counter_set_handle = flow->counter->cs->handle;
999         flow_verbs_spec_add(&dev_flow->verbs, &counter, size);
1000 #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
1001         counter.counters = flow->counter->cs;
1002         flow_verbs_spec_add(&dev_flow->verbs, &counter, size);
1003 #endif
1004         return 0;
1005 }
1006
1007 /**
1008  * Internal validation function. For validating both actions and items.
1009  *
1010  * @param[in] dev
1011  *   Pointer to the Ethernet device structure.
1012  * @param[in] attr
1013  *   Pointer to the flow attributes.
1014  * @param[in] items
1015  *   Pointer to the list of items.
1016  * @param[in] actions
1017  *   Pointer to the list of actions.
1018  * @param[in] external
1019  *   This flow rule is created by request external to PMD.
1020  * @param[out] error
1021  *   Pointer to the error structure.
1022  *
1023  * @return
1024  *   0 on success, a negative errno value otherwise and rte_errno is set.
1025  */
1026 static int
1027 flow_verbs_validate(struct rte_eth_dev *dev,
1028                     const struct rte_flow_attr *attr,
1029                     const struct rte_flow_item items[],
1030                     const struct rte_flow_action actions[],
1031                     bool external __rte_unused,
1032                     struct rte_flow_error *error)
1033 {
1034         int ret;
1035         uint64_t action_flags = 0;
1036         uint64_t item_flags = 0;
1037         uint64_t last_item = 0;
1038         uint8_t next_protocol = 0xff;
1039         uint16_t ether_type = 0;
1040
1041         if (items == NULL)
1042                 return -1;
1043         ret = mlx5_flow_validate_attributes(dev, attr, error);
1044         if (ret < 0)
1045                 return ret;
1046         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
1047                 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
1048                 int ret = 0;
1049
1050                 switch (items->type) {
1051                 case RTE_FLOW_ITEM_TYPE_VOID:
1052                         break;
1053                 case RTE_FLOW_ITEM_TYPE_ETH:
1054                         ret = mlx5_flow_validate_item_eth(items, item_flags,
1055                                                           error);
1056                         if (ret < 0)
1057                                 return ret;
1058                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
1059                                              MLX5_FLOW_LAYER_OUTER_L2;
1060                         if (items->mask != NULL && items->spec != NULL) {
1061                                 ether_type =
1062                                         ((const struct rte_flow_item_eth *)
1063                                          items->spec)->type;
1064                                 ether_type &=
1065                                         ((const struct rte_flow_item_eth *)
1066                                          items->mask)->type;
1067                                 ether_type = rte_be_to_cpu_16(ether_type);
1068                         } else {
1069                                 ether_type = 0;
1070                         }
1071                         break;
1072                 case RTE_FLOW_ITEM_TYPE_VLAN:
1073                         ret = mlx5_flow_validate_item_vlan(items, item_flags,
1074                                                            dev, error);
1075                         if (ret < 0)
1076                                 return ret;
1077                         last_item = tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
1078                                               MLX5_FLOW_LAYER_INNER_VLAN) :
1079                                              (MLX5_FLOW_LAYER_OUTER_L2 |
1080                                               MLX5_FLOW_LAYER_OUTER_VLAN);
1081                         if (items->mask != NULL && items->spec != NULL) {
1082                                 ether_type =
1083                                         ((const struct rte_flow_item_vlan *)
1084                                          items->spec)->inner_type;
1085                                 ether_type &=
1086                                         ((const struct rte_flow_item_vlan *)
1087                                          items->mask)->inner_type;
1088                                 ether_type = rte_be_to_cpu_16(ether_type);
1089                         } else {
1090                                 ether_type = 0;
1091                         }
1092                         break;
1093                 case RTE_FLOW_ITEM_TYPE_IPV4:
1094                         ret = mlx5_flow_validate_item_ipv4(items, item_flags,
1095                                                            last_item,
1096                                                            ether_type, NULL,
1097                                                            error);
1098                         if (ret < 0)
1099                                 return ret;
1100                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
1101                                              MLX5_FLOW_LAYER_OUTER_L3_IPV4;
1102                         if (items->mask != NULL &&
1103                             ((const struct rte_flow_item_ipv4 *)
1104                              items->mask)->hdr.next_proto_id) {
1105                                 next_protocol =
1106                                         ((const struct rte_flow_item_ipv4 *)
1107                                          (items->spec))->hdr.next_proto_id;
1108                                 next_protocol &=
1109                                         ((const struct rte_flow_item_ipv4 *)
1110                                          (items->mask))->hdr.next_proto_id;
1111                         } else {
1112                                 /* Reset for inner layer. */
1113                                 next_protocol = 0xff;
1114                         }
1115                         break;
1116                 case RTE_FLOW_ITEM_TYPE_IPV6:
1117                         ret = mlx5_flow_validate_item_ipv6(items, item_flags,
1118                                                            last_item,
1119                                                            ether_type, NULL,
1120                                                            error);
1121                         if (ret < 0)
1122                                 return ret;
1123                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
1124                                              MLX5_FLOW_LAYER_OUTER_L3_IPV6;
1125                         if (items->mask != NULL &&
1126                             ((const struct rte_flow_item_ipv6 *)
1127                              items->mask)->hdr.proto) {
1128                                 next_protocol =
1129                                         ((const struct rte_flow_item_ipv6 *)
1130                                          items->spec)->hdr.proto;
1131                                 next_protocol &=
1132                                         ((const struct rte_flow_item_ipv6 *)
1133                                          items->mask)->hdr.proto;
1134                         } else {
1135                                 /* Reset for inner layer. */
1136                                 next_protocol = 0xff;
1137                         }
1138                         break;
1139                 case RTE_FLOW_ITEM_TYPE_UDP:
1140                         ret = mlx5_flow_validate_item_udp(items, item_flags,
1141                                                           next_protocol,
1142                                                           error);
1143                         if (ret < 0)
1144                                 return ret;
1145                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
1146                                              MLX5_FLOW_LAYER_OUTER_L4_UDP;
1147                         break;
1148                 case RTE_FLOW_ITEM_TYPE_TCP:
1149                         ret = mlx5_flow_validate_item_tcp
1150                                                 (items, item_flags,
1151                                                  next_protocol,
1152                                                  &rte_flow_item_tcp_mask,
1153                                                  error);
1154                         if (ret < 0)
1155                                 return ret;
1156                         last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
1157                                              MLX5_FLOW_LAYER_OUTER_L4_TCP;
1158                         break;
1159                 case RTE_FLOW_ITEM_TYPE_VXLAN:
1160                         ret = mlx5_flow_validate_item_vxlan(items, item_flags,
1161                                                             error);
1162                         if (ret < 0)
1163                                 return ret;
1164                         last_item = MLX5_FLOW_LAYER_VXLAN;
1165                         break;
1166                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
1167                         ret = mlx5_flow_validate_item_vxlan_gpe(items,
1168                                                                 item_flags,
1169                                                                 dev, error);
1170                         if (ret < 0)
1171                                 return ret;
1172                         last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
1173                         break;
1174                 case RTE_FLOW_ITEM_TYPE_GRE:
1175                         ret = mlx5_flow_validate_item_gre(items, item_flags,
1176                                                           next_protocol, error);
1177                         if (ret < 0)
1178                                 return ret;
1179                         last_item = MLX5_FLOW_LAYER_GRE;
1180                         break;
1181                 case RTE_FLOW_ITEM_TYPE_MPLS:
1182                         ret = mlx5_flow_validate_item_mpls(dev, items,
1183                                                            item_flags,
1184                                                            last_item, error);
1185                         if (ret < 0)
1186                                 return ret;
1187                         last_item = MLX5_FLOW_LAYER_MPLS;
1188                         break;
1189                 default:
1190                         return rte_flow_error_set(error, ENOTSUP,
1191                                                   RTE_FLOW_ERROR_TYPE_ITEM,
1192                                                   NULL, "item not supported");
1193                 }
1194                 item_flags |= last_item;
1195         }
1196         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1197                 switch (actions->type) {
1198                 case RTE_FLOW_ACTION_TYPE_VOID:
1199                         break;
1200                 case RTE_FLOW_ACTION_TYPE_FLAG:
1201                         ret = mlx5_flow_validate_action_flag(action_flags,
1202                                                              attr,
1203                                                              error);
1204                         if (ret < 0)
1205                                 return ret;
1206                         action_flags |= MLX5_FLOW_ACTION_FLAG;
1207                         break;
1208                 case RTE_FLOW_ACTION_TYPE_MARK:
1209                         ret = mlx5_flow_validate_action_mark(actions,
1210                                                              action_flags,
1211                                                              attr,
1212                                                              error);
1213                         if (ret < 0)
1214                                 return ret;
1215                         action_flags |= MLX5_FLOW_ACTION_MARK;
1216                         break;
1217                 case RTE_FLOW_ACTION_TYPE_DROP:
1218                         ret = mlx5_flow_validate_action_drop(action_flags,
1219                                                              attr,
1220                                                              error);
1221                         if (ret < 0)
1222                                 return ret;
1223                         action_flags |= MLX5_FLOW_ACTION_DROP;
1224                         break;
1225                 case RTE_FLOW_ACTION_TYPE_QUEUE:
1226                         ret = mlx5_flow_validate_action_queue(actions,
1227                                                               action_flags, dev,
1228                                                               attr,
1229                                                               error);
1230                         if (ret < 0)
1231                                 return ret;
1232                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
1233                         break;
1234                 case RTE_FLOW_ACTION_TYPE_RSS:
1235                         ret = mlx5_flow_validate_action_rss(actions,
1236                                                             action_flags, dev,
1237                                                             attr, item_flags,
1238                                                             error);
1239                         if (ret < 0)
1240                                 return ret;
1241                         action_flags |= MLX5_FLOW_ACTION_RSS;
1242                         break;
1243                 case RTE_FLOW_ACTION_TYPE_COUNT:
1244                         ret = mlx5_flow_validate_action_count(dev, attr, error);
1245                         if (ret < 0)
1246                                 return ret;
1247                         action_flags |= MLX5_FLOW_ACTION_COUNT;
1248                         break;
1249                 default:
1250                         return rte_flow_error_set(error, ENOTSUP,
1251                                                   RTE_FLOW_ERROR_TYPE_ACTION,
1252                                                   actions,
1253                                                   "action not supported");
1254                 }
1255         }
1256         /*
1257          * Validate the drop action mutual exclusion with other actions.
1258          * Drop action is mutually-exclusive with any other action, except for
1259          * Count action.
1260          */
1261         if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
1262             (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_COUNT)))
1263                 return rte_flow_error_set(error, EINVAL,
1264                                           RTE_FLOW_ERROR_TYPE_ACTION, NULL,
1265                                           "Drop action is mutually-exclusive "
1266                                           "with any other action, except for "
1267                                           "Count action");
1268         if (!(action_flags & MLX5_FLOW_FATE_ACTIONS))
1269                 return rte_flow_error_set(error, EINVAL,
1270                                           RTE_FLOW_ERROR_TYPE_ACTION, actions,
1271                                           "no fate action is found");
1272         return 0;
1273 }
1274
1275 /**
1276  * Calculate the required bytes that are needed for the action part of the verbs
1277  * flow.
1278  *
1279  * @param[in] actions
1280  *   Pointer to the list of actions.
1281  *
1282  * @return
1283  *   The size of the memory needed for all actions.
1284  */
1285 static int
1286 flow_verbs_get_actions_size(const struct rte_flow_action actions[])
1287 {
1288         int size = 0;
1289
1290         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1291                 switch (actions->type) {
1292                 case RTE_FLOW_ACTION_TYPE_VOID:
1293                         break;
1294                 case RTE_FLOW_ACTION_TYPE_FLAG:
1295                         size += sizeof(struct ibv_flow_spec_action_tag);
1296                         break;
1297                 case RTE_FLOW_ACTION_TYPE_MARK:
1298                         size += sizeof(struct ibv_flow_spec_action_tag);
1299                         break;
1300                 case RTE_FLOW_ACTION_TYPE_DROP:
1301                         size += sizeof(struct ibv_flow_spec_action_drop);
1302                         break;
1303                 case RTE_FLOW_ACTION_TYPE_QUEUE:
1304                         break;
1305                 case RTE_FLOW_ACTION_TYPE_RSS:
1306                         break;
1307                 case RTE_FLOW_ACTION_TYPE_COUNT:
1308 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42) || \
1309         defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
1310                         size += sizeof(struct ibv_flow_spec_counter_action);
1311 #endif
1312                         break;
1313                 default:
1314                         break;
1315                 }
1316         }
1317         return size;
1318 }
1319
1320 /**
1321  * Calculate the required bytes that are needed for the item part of the verbs
1322  * flow.
1323  *
1324  * @param[in] items
1325  *   Pointer to the list of items.
1326  *
1327  * @return
1328  *   The size of the memory needed for all items.
1329  */
1330 static int
1331 flow_verbs_get_items_size(const struct rte_flow_item items[])
1332 {
1333         int size = 0;
1334
1335         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
1336                 switch (items->type) {
1337                 case RTE_FLOW_ITEM_TYPE_VOID:
1338                         break;
1339                 case RTE_FLOW_ITEM_TYPE_ETH:
1340                         size += sizeof(struct ibv_flow_spec_eth);
1341                         break;
1342                 case RTE_FLOW_ITEM_TYPE_VLAN:
1343                         size += sizeof(struct ibv_flow_spec_eth);
1344                         break;
1345                 case RTE_FLOW_ITEM_TYPE_IPV4:
1346                         size += sizeof(struct ibv_flow_spec_ipv4_ext);
1347                         break;
1348                 case RTE_FLOW_ITEM_TYPE_IPV6:
1349                         size += sizeof(struct ibv_flow_spec_ipv6);
1350                         break;
1351                 case RTE_FLOW_ITEM_TYPE_UDP:
1352                         size += sizeof(struct ibv_flow_spec_tcp_udp);
1353                         break;
1354                 case RTE_FLOW_ITEM_TYPE_TCP:
1355                         size += sizeof(struct ibv_flow_spec_tcp_udp);
1356                         break;
1357                 case RTE_FLOW_ITEM_TYPE_VXLAN:
1358                         size += sizeof(struct ibv_flow_spec_tunnel);
1359                         break;
1360                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
1361                         size += sizeof(struct ibv_flow_spec_tunnel);
1362                         break;
1363 #ifdef HAVE_IBV_DEVICE_MPLS_SUPPORT
1364                 case RTE_FLOW_ITEM_TYPE_GRE:
1365                         size += sizeof(struct ibv_flow_spec_gre);
1366                         break;
1367                 case RTE_FLOW_ITEM_TYPE_MPLS:
1368                         size += sizeof(struct ibv_flow_spec_mpls);
1369                         break;
1370 #else
1371                 case RTE_FLOW_ITEM_TYPE_GRE:
1372                         size += sizeof(struct ibv_flow_spec_tunnel);
1373                         break;
1374 #endif
1375                 default:
1376                         break;
1377                 }
1378         }
1379         return size;
1380 }
1381
1382 /**
1383  * Internal preparation function. Allocate mlx5_flow with the required size.
1384  * The required size is calculate based on the actions and items. This function
1385  * also returns the detected actions and items for later use.
1386  *
1387  * @param[in] attr
1388  *   Pointer to the flow attributes.
1389  * @param[in] items
1390  *   Pointer to the list of items.
1391  * @param[in] actions
1392  *   Pointer to the list of actions.
1393  * @param[out] error
1394  *   Pointer to the error structure.
1395  *
1396  * @return
1397  *   Pointer to mlx5_flow object on success, otherwise NULL and rte_errno
1398  *   is set.
1399  */
1400 static struct mlx5_flow *
1401 flow_verbs_prepare(const struct rte_flow_attr *attr __rte_unused,
1402                    const struct rte_flow_item items[],
1403                    const struct rte_flow_action actions[],
1404                    struct rte_flow_error *error)
1405 {
1406         size_t size = sizeof(struct mlx5_flow) + sizeof(struct ibv_flow_attr);
1407         struct mlx5_flow *dev_flow;
1408
1409         size += flow_verbs_get_actions_size(actions);
1410         size += flow_verbs_get_items_size(items);
1411         dev_flow = rte_calloc(__func__, 1, size, 0);
1412         if (!dev_flow) {
1413                 rte_flow_error_set(error, ENOMEM,
1414                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1415                                    "not enough memory to create flow");
1416                 return NULL;
1417         }
1418         dev_flow->verbs.attr = (void *)(dev_flow + 1);
1419         dev_flow->verbs.specs = (void *)(dev_flow->verbs.attr + 1);
1420         dev_flow->ingress = attr->ingress;
1421         dev_flow->transfer = attr->transfer;
1422         return dev_flow;
1423 }
1424
1425 /**
1426  * Fill the flow with verb spec.
1427  *
1428  * @param[in] dev
1429  *   Pointer to Ethernet device.
1430  * @param[in, out] dev_flow
1431  *   Pointer to the mlx5 flow.
1432  * @param[in] attr
1433  *   Pointer to the flow attributes.
1434  * @param[in] items
1435  *   Pointer to the list of items.
1436  * @param[in] actions
1437  *   Pointer to the list of actions.
1438  * @param[out] error
1439  *   Pointer to the error structure.
1440  *
1441  * @return
1442  *   0 on success, else a negative errno value otherwise and rte_errno is set.
1443  */
1444 static int
1445 flow_verbs_translate(struct rte_eth_dev *dev,
1446                      struct mlx5_flow *dev_flow,
1447                      const struct rte_flow_attr *attr,
1448                      const struct rte_flow_item items[],
1449                      const struct rte_flow_action actions[],
1450                      struct rte_flow_error *error)
1451 {
1452         uint64_t item_flags = 0;
1453         uint64_t action_flags = 0;
1454         uint64_t priority = attr->priority;
1455         uint32_t subpriority = 0;
1456         struct mlx5_priv *priv = dev->data->dev_private;
1457
1458         if (priority == MLX5_FLOW_PRIO_RSVD)
1459                 priority = priv->config.flow_prio - 1;
1460         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1461                 int ret;
1462
1463                 switch (actions->type) {
1464                 case RTE_FLOW_ACTION_TYPE_VOID:
1465                         break;
1466                 case RTE_FLOW_ACTION_TYPE_FLAG:
1467                         flow_verbs_translate_action_flag(dev_flow, actions);
1468                         action_flags |= MLX5_FLOW_ACTION_FLAG;
1469                         break;
1470                 case RTE_FLOW_ACTION_TYPE_MARK:
1471                         flow_verbs_translate_action_mark(dev_flow, actions);
1472                         action_flags |= MLX5_FLOW_ACTION_MARK;
1473                         break;
1474                 case RTE_FLOW_ACTION_TYPE_DROP:
1475                         flow_verbs_translate_action_drop(dev_flow, actions);
1476                         action_flags |= MLX5_FLOW_ACTION_DROP;
1477                         break;
1478                 case RTE_FLOW_ACTION_TYPE_QUEUE:
1479                         flow_verbs_translate_action_queue(dev_flow, actions);
1480                         action_flags |= MLX5_FLOW_ACTION_QUEUE;
1481                         break;
1482                 case RTE_FLOW_ACTION_TYPE_RSS:
1483                         flow_verbs_translate_action_rss(dev_flow, actions);
1484                         action_flags |= MLX5_FLOW_ACTION_RSS;
1485                         break;
1486                 case RTE_FLOW_ACTION_TYPE_COUNT:
1487                         ret = flow_verbs_translate_action_count(dev_flow,
1488                                                                 actions,
1489                                                                 dev, error);
1490                         if (ret < 0)
1491                                 return ret;
1492                         action_flags |= MLX5_FLOW_ACTION_COUNT;
1493                         break;
1494                 default:
1495                         return rte_flow_error_set(error, ENOTSUP,
1496                                                   RTE_FLOW_ERROR_TYPE_ACTION,
1497                                                   actions,
1498                                                   "action not supported");
1499                 }
1500         }
1501         dev_flow->actions = action_flags;
1502         for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
1503                 int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
1504
1505                 switch (items->type) {
1506                 case RTE_FLOW_ITEM_TYPE_VOID:
1507                         break;
1508                 case RTE_FLOW_ITEM_TYPE_ETH:
1509                         flow_verbs_translate_item_eth(dev_flow, items,
1510                                                       item_flags);
1511                         subpriority = MLX5_PRIORITY_MAP_L2;
1512                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L2 :
1513                                                MLX5_FLOW_LAYER_OUTER_L2;
1514                         break;
1515                 case RTE_FLOW_ITEM_TYPE_VLAN:
1516                         flow_verbs_translate_item_vlan(dev_flow, items,
1517                                                        item_flags);
1518                         subpriority = MLX5_PRIORITY_MAP_L2;
1519                         item_flags |= tunnel ? (MLX5_FLOW_LAYER_INNER_L2 |
1520                                                 MLX5_FLOW_LAYER_INNER_VLAN) :
1521                                                (MLX5_FLOW_LAYER_OUTER_L2 |
1522                                                 MLX5_FLOW_LAYER_OUTER_VLAN);
1523                         break;
1524                 case RTE_FLOW_ITEM_TYPE_IPV4:
1525                         flow_verbs_translate_item_ipv4(dev_flow, items,
1526                                                        item_flags);
1527                         subpriority = MLX5_PRIORITY_MAP_L3;
1528                         dev_flow->hash_fields |=
1529                                 mlx5_flow_hashfields_adjust
1530                                         (dev_flow, tunnel,
1531                                          MLX5_IPV4_LAYER_TYPES,
1532                                          MLX5_IPV4_IBV_RX_HASH);
1533                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
1534                                                MLX5_FLOW_LAYER_OUTER_L3_IPV4;
1535                         break;
1536                 case RTE_FLOW_ITEM_TYPE_IPV6:
1537                         flow_verbs_translate_item_ipv6(dev_flow, items,
1538                                                        item_flags);
1539                         subpriority = MLX5_PRIORITY_MAP_L3;
1540                         dev_flow->hash_fields |=
1541                                 mlx5_flow_hashfields_adjust
1542                                         (dev_flow, tunnel,
1543                                          MLX5_IPV6_LAYER_TYPES,
1544                                          MLX5_IPV6_IBV_RX_HASH);
1545                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
1546                                                MLX5_FLOW_LAYER_OUTER_L3_IPV6;
1547                         break;
1548                 case RTE_FLOW_ITEM_TYPE_TCP:
1549                         flow_verbs_translate_item_tcp(dev_flow, items,
1550                                                       item_flags);
1551                         subpriority = MLX5_PRIORITY_MAP_L4;
1552                         dev_flow->hash_fields |=
1553                                 mlx5_flow_hashfields_adjust
1554                                         (dev_flow, tunnel, ETH_RSS_TCP,
1555                                          (IBV_RX_HASH_SRC_PORT_TCP |
1556                                           IBV_RX_HASH_DST_PORT_TCP));
1557                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
1558                                                MLX5_FLOW_LAYER_OUTER_L4_TCP;
1559                         break;
1560                 case RTE_FLOW_ITEM_TYPE_UDP:
1561                         flow_verbs_translate_item_udp(dev_flow, items,
1562                                                       item_flags);
1563                         subpriority = MLX5_PRIORITY_MAP_L4;
1564                         dev_flow->hash_fields |=
1565                                 mlx5_flow_hashfields_adjust
1566                                         (dev_flow, tunnel, ETH_RSS_UDP,
1567                                          (IBV_RX_HASH_SRC_PORT_UDP |
1568                                           IBV_RX_HASH_DST_PORT_UDP));
1569                         item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
1570                                                MLX5_FLOW_LAYER_OUTER_L4_UDP;
1571                         break;
1572                 case RTE_FLOW_ITEM_TYPE_VXLAN:
1573                         flow_verbs_translate_item_vxlan(dev_flow, items,
1574                                                         item_flags);
1575                         subpriority = MLX5_PRIORITY_MAP_L2;
1576                         item_flags |= MLX5_FLOW_LAYER_VXLAN;
1577                         break;
1578                 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
1579                         flow_verbs_translate_item_vxlan_gpe(dev_flow, items,
1580                                                             item_flags);
1581                         subpriority = MLX5_PRIORITY_MAP_L2;
1582                         item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
1583                         break;
1584                 case RTE_FLOW_ITEM_TYPE_GRE:
1585                         flow_verbs_translate_item_gre(dev_flow, items,
1586                                                       item_flags);
1587                         subpriority = MLX5_PRIORITY_MAP_L2;
1588                         item_flags |= MLX5_FLOW_LAYER_GRE;
1589                         break;
1590                 case RTE_FLOW_ITEM_TYPE_MPLS:
1591                         flow_verbs_translate_item_mpls(dev_flow, items,
1592                                                        item_flags);
1593                         subpriority = MLX5_PRIORITY_MAP_L2;
1594                         item_flags |= MLX5_FLOW_LAYER_MPLS;
1595                         break;
1596                 default:
1597                         return rte_flow_error_set(error, ENOTSUP,
1598                                                   RTE_FLOW_ERROR_TYPE_ITEM,
1599                                                   NULL,
1600                                                   "item not supported");
1601                 }
1602         }
1603         dev_flow->layers = item_flags;
1604         dev_flow->verbs.attr->priority =
1605                 mlx5_flow_adjust_priority(dev, priority, subpriority);
1606         dev_flow->verbs.attr->port = (uint8_t)priv->ibv_port;
1607         return 0;
1608 }
1609
1610 /**
1611  * Remove the flow from the NIC but keeps it in memory.
1612  *
1613  * @param[in] dev
1614  *   Pointer to the Ethernet device structure.
1615  * @param[in, out] flow
1616  *   Pointer to flow structure.
1617  */
1618 static void
1619 flow_verbs_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
1620 {
1621         struct mlx5_flow_verbs *verbs;
1622         struct mlx5_flow *dev_flow;
1623
1624         if (!flow)
1625                 return;
1626         LIST_FOREACH(dev_flow, &flow->dev_flows, next) {
1627                 verbs = &dev_flow->verbs;
1628                 if (verbs->flow) {
1629                         claim_zero(mlx5_glue->destroy_flow(verbs->flow));
1630                         verbs->flow = NULL;
1631                 }
1632                 if (verbs->hrxq) {
1633                         if (dev_flow->actions & MLX5_FLOW_ACTION_DROP)
1634                                 mlx5_hrxq_drop_release(dev);
1635                         else
1636                                 mlx5_hrxq_release(dev, verbs->hrxq);
1637                         verbs->hrxq = NULL;
1638                 }
1639                 if (dev_flow->verbs.vf_vlan.tag &&
1640                     dev_flow->verbs.vf_vlan.created) {
1641                         mlx5_vlan_vmwa_release(dev, &dev_flow->verbs.vf_vlan);
1642                 }
1643         }
1644 }
1645
1646 /**
1647  * Remove the flow from the NIC and the memory.
1648  *
1649  * @param[in] dev
1650  *   Pointer to the Ethernet device structure.
1651  * @param[in, out] flow
1652  *   Pointer to flow structure.
1653  */
1654 static void
1655 flow_verbs_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
1656 {
1657         struct mlx5_flow *dev_flow;
1658
1659         if (!flow)
1660                 return;
1661         flow_verbs_remove(dev, flow);
1662         while (!LIST_EMPTY(&flow->dev_flows)) {
1663                 dev_flow = LIST_FIRST(&flow->dev_flows);
1664                 LIST_REMOVE(dev_flow, next);
1665                 rte_free(dev_flow);
1666         }
1667         if (flow->counter) {
1668                 flow_verbs_counter_release(dev, flow->counter);
1669                 flow->counter = NULL;
1670         }
1671 }
1672
1673 /**
1674  * Apply the flow to the NIC.
1675  *
1676  * @param[in] dev
1677  *   Pointer to the Ethernet device structure.
1678  * @param[in, out] flow
1679  *   Pointer to flow structure.
1680  * @param[out] error
1681  *   Pointer to error structure.
1682  *
1683  * @return
1684  *   0 on success, a negative errno value otherwise and rte_errno is set.
1685  */
1686 static int
1687 flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
1688                  struct rte_flow_error *error)
1689 {
1690         struct mlx5_priv *priv = dev->data->dev_private;
1691         struct mlx5_flow_verbs *verbs;
1692         struct mlx5_flow *dev_flow;
1693         int err;
1694
1695         LIST_FOREACH(dev_flow, &flow->dev_flows, next) {
1696                 verbs = &dev_flow->verbs;
1697                 if (dev_flow->actions & MLX5_FLOW_ACTION_DROP) {
1698                         verbs->hrxq = mlx5_hrxq_drop_new(dev);
1699                         if (!verbs->hrxq) {
1700                                 rte_flow_error_set
1701                                         (error, errno,
1702                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1703                                          "cannot get drop hash queue");
1704                                 goto error;
1705                         }
1706                 } else {
1707                         struct mlx5_hrxq *hrxq;
1708
1709                         MLX5_ASSERT(flow->rss.queue);
1710                         hrxq = mlx5_hrxq_get(dev, flow->rss.key,
1711                                              MLX5_RSS_HASH_KEY_LEN,
1712                                              dev_flow->hash_fields,
1713                                              (*flow->rss.queue),
1714                                              flow->rss.queue_num);
1715                         if (!hrxq)
1716                                 hrxq = mlx5_hrxq_new(dev, flow->rss.key,
1717                                                      MLX5_RSS_HASH_KEY_LEN,
1718                                                      dev_flow->hash_fields,
1719                                                      (*flow->rss.queue),
1720                                                      flow->rss.queue_num,
1721                                                      !!(dev_flow->layers &
1722                                                        MLX5_FLOW_LAYER_TUNNEL));
1723                         if (!hrxq) {
1724                                 rte_flow_error_set
1725                                         (error, rte_errno,
1726                                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1727                                          "cannot get hash queue");
1728                                 goto error;
1729                         }
1730                         verbs->hrxq = hrxq;
1731                 }
1732                 verbs->flow = mlx5_glue->create_flow(verbs->hrxq->qp,
1733                                                      verbs->attr);
1734                 if (!verbs->flow) {
1735                         rte_flow_error_set(error, errno,
1736                                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1737                                            NULL,
1738                                            "hardware refuses to create flow");
1739                         goto error;
1740                 }
1741                 if (priv->vmwa_context &&
1742                     dev_flow->verbs.vf_vlan.tag &&
1743                     !dev_flow->verbs.vf_vlan.created) {
1744                         /*
1745                          * The rule contains the VLAN pattern.
1746                          * For VF we are going to create VLAN
1747                          * interface to make hypervisor set correct
1748                          * e-Switch vport context.
1749                          */
1750                         mlx5_vlan_vmwa_acquire(dev, &dev_flow->verbs.vf_vlan);
1751                 }
1752         }
1753         return 0;
1754 error:
1755         err = rte_errno; /* Save rte_errno before cleanup. */
1756         LIST_FOREACH(dev_flow, &flow->dev_flows, next) {
1757                 verbs = &dev_flow->verbs;
1758                 if (verbs->hrxq) {
1759                         if (dev_flow->actions & MLX5_FLOW_ACTION_DROP)
1760                                 mlx5_hrxq_drop_release(dev);
1761                         else
1762                                 mlx5_hrxq_release(dev, verbs->hrxq);
1763                         verbs->hrxq = NULL;
1764                 }
1765                 if (dev_flow->verbs.vf_vlan.tag &&
1766                     dev_flow->verbs.vf_vlan.created) {
1767                         mlx5_vlan_vmwa_release(dev, &dev_flow->verbs.vf_vlan);
1768                 }
1769         }
1770         rte_errno = err; /* Restore rte_errno. */
1771         return -rte_errno;
1772 }
1773
1774 /**
1775  * Query a flow.
1776  *
1777  * @see rte_flow_query()
1778  * @see rte_flow_ops
1779  */
1780 static int
1781 flow_verbs_query(struct rte_eth_dev *dev,
1782                  struct rte_flow *flow,
1783                  const struct rte_flow_action *actions,
1784                  void *data,
1785                  struct rte_flow_error *error)
1786 {
1787         int ret = -EINVAL;
1788
1789         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1790                 switch (actions->type) {
1791                 case RTE_FLOW_ACTION_TYPE_VOID:
1792                         break;
1793                 case RTE_FLOW_ACTION_TYPE_COUNT:
1794                         ret = flow_verbs_counter_query(dev, flow, data, error);
1795                         break;
1796                 default:
1797                         return rte_flow_error_set(error, ENOTSUP,
1798                                                   RTE_FLOW_ERROR_TYPE_ACTION,
1799                                                   actions,
1800                                                   "action not supported");
1801                 }
1802         }
1803         return ret;
1804 }
1805
1806 const struct mlx5_flow_driver_ops mlx5_flow_verbs_drv_ops = {
1807         .validate = flow_verbs_validate,
1808         .prepare = flow_verbs_prepare,
1809         .translate = flow_verbs_translate,
1810         .apply = flow_verbs_apply,
1811         .remove = flow_verbs_remove,
1812         .destroy = flow_verbs_destroy,
1813         .query = flow_verbs_query,
1814 };