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