net/mlx4: clean up coding style inconsistencies
[dpdk.git] / drivers / net / mlx4 / mlx4_flow.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2017 6WIND S.A.
5  *   Copyright 2017 Mellanox
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <assert.h>
35
36 #include <rte_flow.h>
37 #include <rte_flow_driver.h>
38 #include <rte_malloc.h>
39
40 /* PMD headers. */
41 #include "mlx4.h"
42 #include "mlx4_flow.h"
43
44 /** Static initializer for items. */
45 #define ITEMS(...) \
46         (const enum rte_flow_item_type []){ \
47                 __VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
48         }
49
50 /** Structure to generate a simple graph of layers supported by the NIC. */
51 struct mlx4_flow_items {
52         /** List of possible actions for these items. */
53         const enum rte_flow_action_type *const actions;
54         /** Bit-masks corresponding to the possibilities for the item. */
55         const void *mask;
56         /**
57          * Default bit-masks to use when item->mask is not provided. When
58          * \default_mask is also NULL, the full supported bit-mask (\mask) is
59          * used instead.
60          */
61         const void *default_mask;
62         /** Bit-masks size in bytes. */
63         const unsigned int mask_sz;
64         /**
65          * Check support for a given item.
66          *
67          * @param item[in]
68          *   Item specification.
69          * @param mask[in]
70          *   Bit-masks covering supported fields to compare with spec,
71          *   last and mask in
72          *   \item.
73          * @param size
74          *   Bit-Mask size in bytes.
75          *
76          * @return
77          *   0 on success, negative value otherwise.
78          */
79         int (*validate)(const struct rte_flow_item *item,
80                         const uint8_t *mask, unsigned int size);
81         /**
82          * Conversion function from rte_flow to NIC specific flow.
83          *
84          * @param item
85          *   rte_flow item to convert.
86          * @param default_mask
87          *   Default bit-masks to use when item->mask is not provided.
88          * @param data
89          *   Internal structure to store the conversion.
90          *
91          * @return
92          *   0 on success, negative value otherwise.
93          */
94         int (*convert)(const struct rte_flow_item *item,
95                        const void *default_mask,
96                        void *data);
97         /** Size in bytes of the destination structure. */
98         const unsigned int dst_sz;
99         /** List of possible following items.  */
100         const enum rte_flow_item_type *const items;
101 };
102
103 struct rte_flow_drop {
104         struct ibv_qp *qp; /**< Verbs queue pair. */
105         struct ibv_cq *cq; /**< Verbs completion queue. */
106 };
107
108 /** Valid action for this PMD. */
109 static const enum rte_flow_action_type valid_actions[] = {
110         RTE_FLOW_ACTION_TYPE_DROP,
111         RTE_FLOW_ACTION_TYPE_QUEUE,
112         RTE_FLOW_ACTION_TYPE_END,
113 };
114
115 /**
116  * Convert Ethernet item to Verbs specification.
117  *
118  * @param item[in]
119  *   Item specification.
120  * @param default_mask[in]
121  *   Default bit-masks to use when item->mask is not provided.
122  * @param data[in, out]
123  *   User structure.
124  */
125 static int
126 mlx4_flow_create_eth(const struct rte_flow_item *item,
127                      const void *default_mask,
128                      void *data)
129 {
130         const struct rte_flow_item_eth *spec = item->spec;
131         const struct rte_flow_item_eth *mask = item->mask;
132         struct mlx4_flow *flow = (struct mlx4_flow *)data;
133         struct ibv_flow_spec_eth *eth;
134         const unsigned int eth_size = sizeof(struct ibv_flow_spec_eth);
135         unsigned int i;
136
137         ++flow->ibv_attr->num_of_specs;
138         flow->ibv_attr->priority = 2;
139         eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
140         *eth = (struct ibv_flow_spec_eth) {
141                 .type = IBV_FLOW_SPEC_ETH,
142                 .size = eth_size,
143         };
144         if (!spec) {
145                 flow->ibv_attr->type = IBV_FLOW_ATTR_ALL_DEFAULT;
146                 return 0;
147         }
148         if (!mask)
149                 mask = default_mask;
150         memcpy(eth->val.dst_mac, spec->dst.addr_bytes, ETHER_ADDR_LEN);
151         memcpy(eth->val.src_mac, spec->src.addr_bytes, ETHER_ADDR_LEN);
152         memcpy(eth->mask.dst_mac, mask->dst.addr_bytes, ETHER_ADDR_LEN);
153         memcpy(eth->mask.src_mac, mask->src.addr_bytes, ETHER_ADDR_LEN);
154         /* Remove unwanted bits from values. */
155         for (i = 0; i < ETHER_ADDR_LEN; ++i) {
156                 eth->val.dst_mac[i] &= eth->mask.dst_mac[i];
157                 eth->val.src_mac[i] &= eth->mask.src_mac[i];
158         }
159         return 0;
160 }
161
162 /**
163  * Convert VLAN item to Verbs specification.
164  *
165  * @param item[in]
166  *   Item specification.
167  * @param default_mask[in]
168  *   Default bit-masks to use when item->mask is not provided.
169  * @param data[in, out]
170  *   User structure.
171  */
172 static int
173 mlx4_flow_create_vlan(const struct rte_flow_item *item,
174                       const void *default_mask,
175                       void *data)
176 {
177         const struct rte_flow_item_vlan *spec = item->spec;
178         const struct rte_flow_item_vlan *mask = item->mask;
179         struct mlx4_flow *flow = (struct mlx4_flow *)data;
180         struct ibv_flow_spec_eth *eth;
181         const unsigned int eth_size = sizeof(struct ibv_flow_spec_eth);
182
183         eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset - eth_size);
184         if (!spec)
185                 return 0;
186         if (!mask)
187                 mask = default_mask;
188         eth->val.vlan_tag = spec->tci;
189         eth->mask.vlan_tag = mask->tci;
190         eth->val.vlan_tag &= eth->mask.vlan_tag;
191         return 0;
192 }
193
194 /**
195  * Convert IPv4 item to Verbs specification.
196  *
197  * @param item[in]
198  *   Item specification.
199  * @param default_mask[in]
200  *   Default bit-masks to use when item->mask is not provided.
201  * @param data[in, out]
202  *   User structure.
203  */
204 static int
205 mlx4_flow_create_ipv4(const struct rte_flow_item *item,
206                       const void *default_mask,
207                       void *data)
208 {
209         const struct rte_flow_item_ipv4 *spec = item->spec;
210         const struct rte_flow_item_ipv4 *mask = item->mask;
211         struct mlx4_flow *flow = (struct mlx4_flow *)data;
212         struct ibv_flow_spec_ipv4 *ipv4;
213         unsigned int ipv4_size = sizeof(struct ibv_flow_spec_ipv4);
214
215         ++flow->ibv_attr->num_of_specs;
216         flow->ibv_attr->priority = 1;
217         ipv4 = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
218         *ipv4 = (struct ibv_flow_spec_ipv4) {
219                 .type = IBV_FLOW_SPEC_IPV4,
220                 .size = ipv4_size,
221         };
222         if (!spec)
223                 return 0;
224         ipv4->val = (struct ibv_flow_ipv4_filter) {
225                 .src_ip = spec->hdr.src_addr,
226                 .dst_ip = spec->hdr.dst_addr,
227         };
228         if (!mask)
229                 mask = default_mask;
230         ipv4->mask = (struct ibv_flow_ipv4_filter) {
231                 .src_ip = mask->hdr.src_addr,
232                 .dst_ip = mask->hdr.dst_addr,
233         };
234         /* Remove unwanted bits from values. */
235         ipv4->val.src_ip &= ipv4->mask.src_ip;
236         ipv4->val.dst_ip &= ipv4->mask.dst_ip;
237         return 0;
238 }
239
240 /**
241  * Convert UDP item to Verbs specification.
242  *
243  * @param item[in]
244  *   Item specification.
245  * @param default_mask[in]
246  *   Default bit-masks to use when item->mask is not provided.
247  * @param data[in, out]
248  *   User structure.
249  */
250 static int
251 mlx4_flow_create_udp(const struct rte_flow_item *item,
252                      const void *default_mask,
253                      void *data)
254 {
255         const struct rte_flow_item_udp *spec = item->spec;
256         const struct rte_flow_item_udp *mask = item->mask;
257         struct mlx4_flow *flow = (struct mlx4_flow *)data;
258         struct ibv_flow_spec_tcp_udp *udp;
259         unsigned int udp_size = sizeof(struct ibv_flow_spec_tcp_udp);
260
261         ++flow->ibv_attr->num_of_specs;
262         flow->ibv_attr->priority = 0;
263         udp = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
264         *udp = (struct ibv_flow_spec_tcp_udp) {
265                 .type = IBV_FLOW_SPEC_UDP,
266                 .size = udp_size,
267         };
268         if (!spec)
269                 return 0;
270         udp->val.dst_port = spec->hdr.dst_port;
271         udp->val.src_port = spec->hdr.src_port;
272         if (!mask)
273                 mask = default_mask;
274         udp->mask.dst_port = mask->hdr.dst_port;
275         udp->mask.src_port = mask->hdr.src_port;
276         /* Remove unwanted bits from values. */
277         udp->val.src_port &= udp->mask.src_port;
278         udp->val.dst_port &= udp->mask.dst_port;
279         return 0;
280 }
281
282 /**
283  * Convert TCP item to Verbs specification.
284  *
285  * @param item[in]
286  *   Item specification.
287  * @param default_mask[in]
288  *   Default bit-masks to use when item->mask is not provided.
289  * @param data[in, out]
290  *   User structure.
291  */
292 static int
293 mlx4_flow_create_tcp(const struct rte_flow_item *item,
294                      const void *default_mask,
295                      void *data)
296 {
297         const struct rte_flow_item_tcp *spec = item->spec;
298         const struct rte_flow_item_tcp *mask = item->mask;
299         struct mlx4_flow *flow = (struct mlx4_flow *)data;
300         struct ibv_flow_spec_tcp_udp *tcp;
301         unsigned int tcp_size = sizeof(struct ibv_flow_spec_tcp_udp);
302
303         ++flow->ibv_attr->num_of_specs;
304         flow->ibv_attr->priority = 0;
305         tcp = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
306         *tcp = (struct ibv_flow_spec_tcp_udp) {
307                 .type = IBV_FLOW_SPEC_TCP,
308                 .size = tcp_size,
309         };
310         if (!spec)
311                 return 0;
312         tcp->val.dst_port = spec->hdr.dst_port;
313         tcp->val.src_port = spec->hdr.src_port;
314         if (!mask)
315                 mask = default_mask;
316         tcp->mask.dst_port = mask->hdr.dst_port;
317         tcp->mask.src_port = mask->hdr.src_port;
318         /* Remove unwanted bits from values. */
319         tcp->val.src_port &= tcp->mask.src_port;
320         tcp->val.dst_port &= tcp->mask.dst_port;
321         return 0;
322 }
323
324 /**
325  * Check support for a given item.
326  *
327  * @param item[in]
328  *   Item specification.
329  * @param mask[in]
330  *   Bit-masks covering supported fields to compare with spec, last and mask in
331  *   \item.
332  * @param size
333  *   Bit-Mask size in bytes.
334  *
335  * @return
336  *   0 on success, negative value otherwise.
337  */
338 static int
339 mlx4_flow_item_validate(const struct rte_flow_item *item,
340                         const uint8_t *mask, unsigned int size)
341 {
342         int ret = 0;
343
344         if (!item->spec && (item->mask || item->last))
345                 return -1;
346         if (item->spec && !item->mask) {
347                 unsigned int i;
348                 const uint8_t *spec = item->spec;
349
350                 for (i = 0; i < size; ++i)
351                         if ((spec[i] | mask[i]) != mask[i])
352                                 return -1;
353         }
354         if (item->last && !item->mask) {
355                 unsigned int i;
356                 const uint8_t *spec = item->last;
357
358                 for (i = 0; i < size; ++i)
359                         if ((spec[i] | mask[i]) != mask[i])
360                                 return -1;
361         }
362         if (item->spec && item->last) {
363                 uint8_t spec[size];
364                 uint8_t last[size];
365                 const uint8_t *apply = mask;
366                 unsigned int i;
367
368                 if (item->mask)
369                         apply = item->mask;
370                 for (i = 0; i < size; ++i) {
371                         spec[i] = ((const uint8_t *)item->spec)[i] & apply[i];
372                         last[i] = ((const uint8_t *)item->last)[i] & apply[i];
373                 }
374                 ret = memcmp(spec, last, size);
375         }
376         return ret;
377 }
378
379 static int
380 mlx4_flow_validate_eth(const struct rte_flow_item *item,
381                        const uint8_t *mask, unsigned int size)
382 {
383         if (item->mask) {
384                 const struct rte_flow_item_eth *mask = item->mask;
385
386                 if (mask->dst.addr_bytes[0] != 0xff ||
387                                 mask->dst.addr_bytes[1] != 0xff ||
388                                 mask->dst.addr_bytes[2] != 0xff ||
389                                 mask->dst.addr_bytes[3] != 0xff ||
390                                 mask->dst.addr_bytes[4] != 0xff ||
391                                 mask->dst.addr_bytes[5] != 0xff)
392                         return -1;
393         }
394         return mlx4_flow_item_validate(item, mask, size);
395 }
396
397 static int
398 mlx4_flow_validate_vlan(const struct rte_flow_item *item,
399                         const uint8_t *mask, unsigned int size)
400 {
401         if (item->mask) {
402                 const struct rte_flow_item_vlan *mask = item->mask;
403
404                 if (mask->tci != 0 &&
405                     ntohs(mask->tci) != 0x0fff)
406                         return -1;
407         }
408         return mlx4_flow_item_validate(item, mask, size);
409 }
410
411 static int
412 mlx4_flow_validate_ipv4(const struct rte_flow_item *item,
413                         const uint8_t *mask, unsigned int size)
414 {
415         if (item->mask) {
416                 const struct rte_flow_item_ipv4 *mask = item->mask;
417
418                 if (mask->hdr.src_addr != 0 &&
419                     mask->hdr.src_addr != 0xffffffff)
420                         return -1;
421                 if (mask->hdr.dst_addr != 0 &&
422                     mask->hdr.dst_addr != 0xffffffff)
423                         return -1;
424         }
425         return mlx4_flow_item_validate(item, mask, size);
426 }
427
428 static int
429 mlx4_flow_validate_udp(const struct rte_flow_item *item,
430                        const uint8_t *mask, unsigned int size)
431 {
432         if (item->mask) {
433                 const struct rte_flow_item_udp *mask = item->mask;
434
435                 if (mask->hdr.src_port != 0 &&
436                     mask->hdr.src_port != 0xffff)
437                         return -1;
438                 if (mask->hdr.dst_port != 0 &&
439                     mask->hdr.dst_port != 0xffff)
440                         return -1;
441         }
442         return mlx4_flow_item_validate(item, mask, size);
443 }
444
445 static int
446 mlx4_flow_validate_tcp(const struct rte_flow_item *item,
447                        const uint8_t *mask, unsigned int size)
448 {
449         if (item->mask) {
450                 const struct rte_flow_item_tcp *mask = item->mask;
451
452                 if (mask->hdr.src_port != 0 &&
453                     mask->hdr.src_port != 0xffff)
454                         return -1;
455                 if (mask->hdr.dst_port != 0 &&
456                     mask->hdr.dst_port != 0xffff)
457                         return -1;
458         }
459         return mlx4_flow_item_validate(item, mask, size);
460 }
461
462 /** Graph of supported items and associated actions. */
463 static const struct mlx4_flow_items mlx4_flow_items[] = {
464         [RTE_FLOW_ITEM_TYPE_END] = {
465                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH),
466         },
467         [RTE_FLOW_ITEM_TYPE_ETH] = {
468                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_VLAN,
469                                RTE_FLOW_ITEM_TYPE_IPV4),
470                 .actions = valid_actions,
471                 .mask = &(const struct rte_flow_item_eth){
472                         .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
473                         .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
474                 },
475                 .default_mask = &rte_flow_item_eth_mask,
476                 .mask_sz = sizeof(struct rte_flow_item_eth),
477                 .validate = mlx4_flow_validate_eth,
478                 .convert = mlx4_flow_create_eth,
479                 .dst_sz = sizeof(struct ibv_flow_spec_eth),
480         },
481         [RTE_FLOW_ITEM_TYPE_VLAN] = {
482                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4),
483                 .actions = valid_actions,
484                 .mask = &(const struct rte_flow_item_vlan){
485                 /* rte_flow_item_vlan_mask is invalid for mlx4. */
486 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
487                         .tci = 0x0fff,
488 #else
489                         .tci = 0xff0f,
490 #endif
491                 },
492                 .mask_sz = sizeof(struct rte_flow_item_vlan),
493                 .validate = mlx4_flow_validate_vlan,
494                 .convert = mlx4_flow_create_vlan,
495                 .dst_sz = 0,
496         },
497         [RTE_FLOW_ITEM_TYPE_IPV4] = {
498                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
499                                RTE_FLOW_ITEM_TYPE_TCP),
500                 .actions = valid_actions,
501                 .mask = &(const struct rte_flow_item_ipv4){
502                         .hdr = {
503                                 .src_addr = -1,
504                                 .dst_addr = -1,
505                         },
506                 },
507                 .default_mask = &rte_flow_item_ipv4_mask,
508                 .mask_sz = sizeof(struct rte_flow_item_ipv4),
509                 .validate = mlx4_flow_validate_ipv4,
510                 .convert = mlx4_flow_create_ipv4,
511                 .dst_sz = sizeof(struct ibv_flow_spec_ipv4),
512         },
513         [RTE_FLOW_ITEM_TYPE_UDP] = {
514                 .actions = valid_actions,
515                 .mask = &(const struct rte_flow_item_udp){
516                         .hdr = {
517                                 .src_port = -1,
518                                 .dst_port = -1,
519                         },
520                 },
521                 .default_mask = &rte_flow_item_udp_mask,
522                 .mask_sz = sizeof(struct rte_flow_item_udp),
523                 .validate = mlx4_flow_validate_udp,
524                 .convert = mlx4_flow_create_udp,
525                 .dst_sz = sizeof(struct ibv_flow_spec_tcp_udp),
526         },
527         [RTE_FLOW_ITEM_TYPE_TCP] = {
528                 .actions = valid_actions,
529                 .mask = &(const struct rte_flow_item_tcp){
530                         .hdr = {
531                                 .src_port = -1,
532                                 .dst_port = -1,
533                         },
534                 },
535                 .default_mask = &rte_flow_item_tcp_mask,
536                 .mask_sz = sizeof(struct rte_flow_item_tcp),
537                 .validate = mlx4_flow_validate_tcp,
538                 .convert = mlx4_flow_create_tcp,
539                 .dst_sz = sizeof(struct ibv_flow_spec_tcp_udp),
540         },
541 };
542
543 /**
544  * Validate a flow supported by the NIC.
545  *
546  * @param priv
547  *   Pointer to private structure.
548  * @param[in] attr
549  *   Flow rule attributes.
550  * @param[in] items
551  *   Pattern specification (list terminated by the END pattern item).
552  * @param[in] actions
553  *   Associated actions (list terminated by the END action).
554  * @param[out] error
555  *   Perform verbose error reporting if not NULL.
556  * @param[in, out] flow
557  *   Flow structure to update.
558  *
559  * @return
560  *   0 on success, a negative errno value otherwise and rte_errno is set.
561  */
562 static int
563 priv_flow_validate(struct priv *priv,
564                    const struct rte_flow_attr *attr,
565                    const struct rte_flow_item items[],
566                    const struct rte_flow_action actions[],
567                    struct rte_flow_error *error,
568                    struct mlx4_flow *flow)
569 {
570         const struct mlx4_flow_items *cur_item = mlx4_flow_items;
571         struct mlx4_flow_action action = {
572                 .queue = 0,
573                 .drop = 0,
574         };
575
576         (void)priv;
577         if (attr->group) {
578                 rte_flow_error_set(error, ENOTSUP,
579                                    RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
580                                    NULL,
581                                    "groups are not supported");
582                 return -rte_errno;
583         }
584         if (attr->priority) {
585                 rte_flow_error_set(error, ENOTSUP,
586                                    RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
587                                    NULL,
588                                    "priorities are not supported");
589                 return -rte_errno;
590         }
591         if (attr->egress) {
592                 rte_flow_error_set(error, ENOTSUP,
593                                    RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
594                                    NULL,
595                                    "egress is not supported");
596                 return -rte_errno;
597         }
598         if (!attr->ingress) {
599                 rte_flow_error_set(error, ENOTSUP,
600                                    RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
601                                    NULL,
602                                    "only ingress is supported");
603                 return -rte_errno;
604         }
605         /* Go over items list. */
606         for (; items->type != RTE_FLOW_ITEM_TYPE_END; ++items) {
607                 const struct mlx4_flow_items *token = NULL;
608                 unsigned int i;
609                 int err;
610
611                 if (items->type == RTE_FLOW_ITEM_TYPE_VOID)
612                         continue;
613                 /*
614                  * The nic can support patterns with NULL eth spec only
615                  * if eth is a single item in a rule.
616                  */
617                 if (!items->spec &&
618                         items->type == RTE_FLOW_ITEM_TYPE_ETH) {
619                         const struct rte_flow_item *next = items + 1;
620
621                         if (next->type != RTE_FLOW_ITEM_TYPE_END) {
622                                 rte_flow_error_set(error, ENOTSUP,
623                                                    RTE_FLOW_ERROR_TYPE_ITEM,
624                                                    items,
625                                                    "the rule requires"
626                                                    " an Ethernet spec");
627                                 return -rte_errno;
628                         }
629                 }
630                 for (i = 0;
631                      cur_item->items &&
632                      cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END;
633                      ++i) {
634                         if (cur_item->items[i] == items->type) {
635                                 token = &mlx4_flow_items[items->type];
636                                 break;
637                         }
638                 }
639                 if (!token)
640                         goto exit_item_not_supported;
641                 cur_item = token;
642                 err = cur_item->validate(items,
643                                         (const uint8_t *)cur_item->mask,
644                                          cur_item->mask_sz);
645                 if (err)
646                         goto exit_item_not_supported;
647                 if (flow->ibv_attr && cur_item->convert) {
648                         err = cur_item->convert(items,
649                                                 (cur_item->default_mask ?
650                                                  cur_item->default_mask :
651                                                  cur_item->mask),
652                                                  flow);
653                         if (err)
654                                 goto exit_item_not_supported;
655                 }
656                 flow->offset += cur_item->dst_sz;
657         }
658         /* Go over actions list */
659         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
660                 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
661                         continue;
662                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
663                         action.drop = 1;
664                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
665                         const struct rte_flow_action_queue *queue =
666                                 (const struct rte_flow_action_queue *)
667                                 actions->conf;
668
669                         if (!queue || (queue->index > (priv->rxqs_n - 1)))
670                                 goto exit_action_not_supported;
671                         action.queue = 1;
672                 } else {
673                         goto exit_action_not_supported;
674                 }
675         }
676         if (!action.queue && !action.drop) {
677                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
678                                    NULL, "no valid action");
679                 return -rte_errno;
680         }
681         return 0;
682 exit_item_not_supported:
683         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
684                            items, "item not supported");
685         return -rte_errno;
686 exit_action_not_supported:
687         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
688                            actions, "action not supported");
689         return -rte_errno;
690 }
691
692 /**
693  * Validate a flow supported by the NIC.
694  *
695  * @see rte_flow_validate()
696  * @see rte_flow_ops
697  */
698 int
699 mlx4_flow_validate(struct rte_eth_dev *dev,
700                    const struct rte_flow_attr *attr,
701                    const struct rte_flow_item items[],
702                    const struct rte_flow_action actions[],
703                    struct rte_flow_error *error)
704 {
705         struct priv *priv = dev->data->dev_private;
706         int ret;
707         struct mlx4_flow flow = { .offset = sizeof(struct ibv_flow_attr) };
708
709         priv_lock(priv);
710         ret = priv_flow_validate(priv, attr, items, actions, error, &flow);
711         priv_unlock(priv);
712         return ret;
713 }
714
715 /**
716  * Destroy a drop queue.
717  *
718  * @param priv
719  *   Pointer to private structure.
720  */
721 static void
722 mlx4_flow_destroy_drop_queue(struct priv *priv)
723 {
724         if (priv->flow_drop_queue) {
725                 struct rte_flow_drop *fdq = priv->flow_drop_queue;
726
727                 priv->flow_drop_queue = NULL;
728                 claim_zero(ibv_destroy_qp(fdq->qp));
729                 claim_zero(ibv_destroy_cq(fdq->cq));
730                 rte_free(fdq);
731         }
732 }
733
734 /**
735  * Create a single drop queue for all drop flows.
736  *
737  * @param priv
738  *   Pointer to private structure.
739  *
740  * @return
741  *   0 on success, negative value otherwise.
742  */
743 static int
744 mlx4_flow_create_drop_queue(struct priv *priv)
745 {
746         struct ibv_qp *qp;
747         struct ibv_cq *cq;
748         struct rte_flow_drop *fdq;
749
750         fdq = rte_calloc(__func__, 1, sizeof(*fdq), 0);
751         if (!fdq) {
752                 ERROR("Cannot allocate memory for drop struct");
753                 goto err;
754         }
755         cq = ibv_create_cq(priv->ctx, 1, NULL, NULL, 0);
756         if (!cq) {
757                 ERROR("Cannot create drop CQ");
758                 goto err_create_cq;
759         }
760         qp = ibv_create_qp(priv->pd,
761                            &(struct ibv_qp_init_attr){
762                                 .send_cq = cq,
763                                 .recv_cq = cq,
764                                 .cap = {
765                                         .max_recv_wr = 1,
766                                         .max_recv_sge = 1,
767                                 },
768                                 .qp_type = IBV_QPT_RAW_PACKET,
769                            });
770         if (!qp) {
771                 ERROR("Cannot create drop QP");
772                 goto err_create_qp;
773         }
774         *fdq = (struct rte_flow_drop){
775                 .qp = qp,
776                 .cq = cq,
777         };
778         priv->flow_drop_queue = fdq;
779         return 0;
780 err_create_qp:
781         claim_zero(ibv_destroy_cq(cq));
782 err_create_cq:
783         rte_free(fdq);
784 err:
785         return -1;
786 }
787
788 /**
789  * Complete flow rule creation.
790  *
791  * @param priv
792  *   Pointer to private structure.
793  * @param ibv_attr
794  *   Verbs flow attributes.
795  * @param action
796  *   Target action structure.
797  * @param[out] error
798  *   Perform verbose error reporting if not NULL.
799  *
800  * @return
801  *   A flow if the rule could be created.
802  */
803 static struct rte_flow *
804 priv_flow_create_action_queue(struct priv *priv,
805                               struct ibv_flow_attr *ibv_attr,
806                               struct mlx4_flow_action *action,
807                               struct rte_flow_error *error)
808 {
809         struct ibv_qp *qp;
810         struct rte_flow *rte_flow;
811
812         assert(priv->pd);
813         assert(priv->ctx);
814         rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0);
815         if (!rte_flow) {
816                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
817                                    NULL, "cannot allocate flow memory");
818                 return NULL;
819         }
820         if (action->drop) {
821                 qp = priv->flow_drop_queue ? priv->flow_drop_queue->qp : NULL;
822         } else {
823                 struct rxq *rxq = (*priv->rxqs)[action->queue_id];
824
825                 qp = rxq->qp;
826                 rte_flow->qp = qp;
827         }
828         rte_flow->ibv_attr = ibv_attr;
829         if (!priv->started)
830                 return rte_flow;
831         rte_flow->ibv_flow = ibv_create_flow(qp, rte_flow->ibv_attr);
832         if (!rte_flow->ibv_flow) {
833                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
834                                    NULL, "flow rule creation failure");
835                 goto error;
836         }
837         return rte_flow;
838 error:
839         rte_free(rte_flow);
840         return NULL;
841 }
842
843 /**
844  * Convert a flow.
845  *
846  * @param priv
847  *   Pointer to private structure.
848  * @param[in] attr
849  *   Flow rule attributes.
850  * @param[in] items
851  *   Pattern specification (list terminated by the END pattern item).
852  * @param[in] actions
853  *   Associated actions (list terminated by the END action).
854  * @param[out] error
855  *   Perform verbose error reporting if not NULL.
856  *
857  * @return
858  *   A flow on success, NULL otherwise.
859  */
860 static struct rte_flow *
861 priv_flow_create(struct priv *priv,
862                  const struct rte_flow_attr *attr,
863                  const struct rte_flow_item items[],
864                  const struct rte_flow_action actions[],
865                  struct rte_flow_error *error)
866 {
867         struct rte_flow *rte_flow;
868         struct mlx4_flow_action action;
869         struct mlx4_flow flow = { .offset = sizeof(struct ibv_flow_attr), };
870         int err;
871
872         err = priv_flow_validate(priv, attr, items, actions, error, &flow);
873         if (err)
874                 return NULL;
875         flow.ibv_attr = rte_malloc(__func__, flow.offset, 0);
876         if (!flow.ibv_attr) {
877                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
878                                    NULL, "cannot allocate ibv_attr memory");
879                 return NULL;
880         }
881         flow.offset = sizeof(struct ibv_flow_attr);
882         *flow.ibv_attr = (struct ibv_flow_attr){
883                 .comp_mask = 0,
884                 .type = IBV_FLOW_ATTR_NORMAL,
885                 .size = sizeof(struct ibv_flow_attr),
886                 .priority = attr->priority,
887                 .num_of_specs = 0,
888                 .port = priv->port,
889                 .flags = 0,
890         };
891         claim_zero(priv_flow_validate(priv, attr, items, actions,
892                                       error, &flow));
893         action = (struct mlx4_flow_action){
894                 .queue = 0,
895                 .drop = 0,
896         };
897         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
898                 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
899                         continue;
900                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
901                         action.queue = 1;
902                         action.queue_id =
903                                 ((const struct rte_flow_action_queue *)
904                                  actions->conf)->index;
905                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
906                         action.drop = 1;
907                 } else {
908                         rte_flow_error_set(error, ENOTSUP,
909                                            RTE_FLOW_ERROR_TYPE_ACTION,
910                                            actions, "unsupported action");
911                         goto exit;
912                 }
913         }
914         rte_flow = priv_flow_create_action_queue(priv, flow.ibv_attr,
915                                                  &action, error);
916         if (rte_flow)
917                 return rte_flow;
918 exit:
919         rte_free(flow.ibv_attr);
920         return NULL;
921 }
922
923 /**
924  * Create a flow.
925  *
926  * @see rte_flow_create()
927  * @see rte_flow_ops
928  */
929 struct rte_flow *
930 mlx4_flow_create(struct rte_eth_dev *dev,
931                  const struct rte_flow_attr *attr,
932                  const struct rte_flow_item items[],
933                  const struct rte_flow_action actions[],
934                  struct rte_flow_error *error)
935 {
936         struct priv *priv = dev->data->dev_private;
937         struct rte_flow *flow;
938
939         priv_lock(priv);
940         flow = priv_flow_create(priv, attr, items, actions, error);
941         if (flow) {
942                 LIST_INSERT_HEAD(&priv->flows, flow, next);
943                 DEBUG("Flow created %p", (void *)flow);
944         }
945         priv_unlock(priv);
946         return flow;
947 }
948
949 /**
950  * @see rte_flow_isolate()
951  *
952  * Must be done before calling dev_configure().
953  *
954  * @param dev
955  *   Pointer to the ethernet device structure.
956  * @param enable
957  *   Nonzero to enter isolated mode, attempt to leave it otherwise.
958  * @param[out] error
959  *   Perform verbose error reporting if not NULL. PMDs initialize this
960  *   structure in case of error only.
961  *
962  * @return
963  *   0 on success, a negative value on error.
964  */
965 int
966 mlx4_flow_isolate(struct rte_eth_dev *dev,
967                   int enable,
968                   struct rte_flow_error *error)
969 {
970         struct priv *priv = dev->data->dev_private;
971
972         priv_lock(priv);
973         if (priv->rxqs) {
974                 rte_flow_error_set(error, ENOTSUP,
975                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
976                                    NULL, "isolated mode must be set"
977                                    " before configuring the device");
978                 priv_unlock(priv);
979                 return -rte_errno;
980         }
981         priv->isolated = !!enable;
982         priv_unlock(priv);
983         return 0;
984 }
985
986 /**
987  * Destroy a flow.
988  *
989  * @param priv
990  *   Pointer to private structure.
991  * @param[in] flow
992  *   Flow to destroy.
993  */
994 static void
995 priv_flow_destroy(struct priv *priv, struct rte_flow *flow)
996 {
997         (void)priv;
998         LIST_REMOVE(flow, next);
999         if (flow->ibv_flow)
1000                 claim_zero(ibv_destroy_flow(flow->ibv_flow));
1001         rte_free(flow->ibv_attr);
1002         DEBUG("Flow destroyed %p", (void *)flow);
1003         rte_free(flow);
1004 }
1005
1006 /**
1007  * Destroy a flow.
1008  *
1009  * @see rte_flow_destroy()
1010  * @see rte_flow_ops
1011  */
1012 int
1013 mlx4_flow_destroy(struct rte_eth_dev *dev,
1014                   struct rte_flow *flow,
1015                   struct rte_flow_error *error)
1016 {
1017         struct priv *priv = dev->data->dev_private;
1018
1019         (void)error;
1020         priv_lock(priv);
1021         priv_flow_destroy(priv, flow);
1022         priv_unlock(priv);
1023         return 0;
1024 }
1025
1026 /**
1027  * Destroy all flows.
1028  *
1029  * @param priv
1030  *   Pointer to private structure.
1031  */
1032 static void
1033 priv_flow_flush(struct priv *priv)
1034 {
1035         while (!LIST_EMPTY(&priv->flows)) {
1036                 struct rte_flow *flow;
1037
1038                 flow = LIST_FIRST(&priv->flows);
1039                 priv_flow_destroy(priv, flow);
1040         }
1041 }
1042
1043 /**
1044  * Destroy all flows.
1045  *
1046  * @see rte_flow_flush()
1047  * @see rte_flow_ops
1048  */
1049 int
1050 mlx4_flow_flush(struct rte_eth_dev *dev,
1051                 struct rte_flow_error *error)
1052 {
1053         struct priv *priv = dev->data->dev_private;
1054
1055         (void)error;
1056         priv_lock(priv);
1057         priv_flow_flush(priv);
1058         priv_unlock(priv);
1059         return 0;
1060 }
1061
1062 /**
1063  * Remove all flows.
1064  *
1065  * Called by dev_stop() to remove all flows.
1066  *
1067  * @param priv
1068  *   Pointer to private structure.
1069  */
1070 void
1071 mlx4_priv_flow_stop(struct priv *priv)
1072 {
1073         struct rte_flow *flow;
1074
1075         for (flow = LIST_FIRST(&priv->flows);
1076              flow;
1077              flow = LIST_NEXT(flow, next)) {
1078                 claim_zero(ibv_destroy_flow(flow->ibv_flow));
1079                 flow->ibv_flow = NULL;
1080                 DEBUG("Flow %p removed", (void *)flow);
1081         }
1082         mlx4_flow_destroy_drop_queue(priv);
1083 }
1084
1085 /**
1086  * Add all flows.
1087  *
1088  * @param priv
1089  *   Pointer to private structure.
1090  *
1091  * @return
1092  *   0 on success, a errno value otherwise and rte_errno is set.
1093  */
1094 int
1095 mlx4_priv_flow_start(struct priv *priv)
1096 {
1097         int ret;
1098         struct ibv_qp *qp;
1099         struct rte_flow *flow;
1100
1101         ret = mlx4_flow_create_drop_queue(priv);
1102         if (ret)
1103                 return -1;
1104         for (flow = LIST_FIRST(&priv->flows);
1105              flow;
1106              flow = LIST_NEXT(flow, next)) {
1107                 qp = flow->qp ? flow->qp : priv->flow_drop_queue->qp;
1108                 flow->ibv_flow = ibv_create_flow(qp, flow->ibv_attr);
1109                 if (!flow->ibv_flow) {
1110                         DEBUG("Flow %p cannot be applied", (void *)flow);
1111                         rte_errno = EINVAL;
1112                         return rte_errno;
1113                 }
1114                 DEBUG("Flow %p applied", (void *)flow);
1115         }
1116         return 0;
1117 }