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