net/sfc: set priority of created filters to manual
[dpdk.git] / drivers / net / sfc / sfc_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2017-2018 Solarflare Communications Inc.
4  * All rights reserved.
5  *
6  * This software was jointly developed between OKTET Labs (under contract
7  * for Solarflare) and Solarflare Communications, Inc.
8  */
9
10 #include <rte_byteorder.h>
11 #include <rte_tailq.h>
12 #include <rte_common.h>
13 #include <rte_ethdev_driver.h>
14 #include <rte_ether.h>
15 #include <rte_flow.h>
16 #include <rte_flow_driver.h>
17
18 #include "efx.h"
19
20 #include "sfc.h"
21 #include "sfc_rx.h"
22 #include "sfc_filter.h"
23 #include "sfc_flow.h"
24 #include "sfc_log.h"
25 #include "sfc_dp_rx.h"
26
27 struct sfc_flow_ops_by_spec {
28         sfc_flow_parse_cb_t     *parse;
29         sfc_flow_insert_cb_t    *insert;
30         sfc_flow_remove_cb_t    *remove;
31 };
32
33 static sfc_flow_parse_cb_t sfc_flow_parse_rte_to_filter;
34 static sfc_flow_insert_cb_t sfc_flow_filter_insert;
35 static sfc_flow_remove_cb_t sfc_flow_filter_remove;
36
37 static const struct sfc_flow_ops_by_spec sfc_flow_ops_filter = {
38         .parse = sfc_flow_parse_rte_to_filter,
39         .insert = sfc_flow_filter_insert,
40         .remove = sfc_flow_filter_remove,
41 };
42
43 static const struct sfc_flow_ops_by_spec *
44 sfc_flow_get_ops_by_spec(struct rte_flow *flow)
45 {
46         struct sfc_flow_spec *spec = &flow->spec;
47         const struct sfc_flow_ops_by_spec *ops = NULL;
48
49         switch (spec->type) {
50         case SFC_FLOW_SPEC_FILTER:
51                 ops = &sfc_flow_ops_filter;
52                 break;
53         default:
54                 SFC_ASSERT(false);
55                 break;
56         }
57
58         return ops;
59 }
60
61 /*
62  * Currently, filter-based (VNIC) flow API is implemented in such a manner
63  * that each flow rule is converted to one or more hardware filters.
64  * All elements of flow rule (attributes, pattern items, actions)
65  * correspond to one or more fields in the efx_filter_spec_s structure
66  * that is responsible for the hardware filter.
67  * If some required field is unset in the flow rule, then a handful
68  * of filter copies will be created to cover all possible values
69  * of such a field.
70  */
71
72 static sfc_flow_item_parse sfc_flow_parse_void;
73 static sfc_flow_item_parse sfc_flow_parse_eth;
74 static sfc_flow_item_parse sfc_flow_parse_vlan;
75 static sfc_flow_item_parse sfc_flow_parse_ipv4;
76 static sfc_flow_item_parse sfc_flow_parse_ipv6;
77 static sfc_flow_item_parse sfc_flow_parse_tcp;
78 static sfc_flow_item_parse sfc_flow_parse_udp;
79 static sfc_flow_item_parse sfc_flow_parse_vxlan;
80 static sfc_flow_item_parse sfc_flow_parse_geneve;
81 static sfc_flow_item_parse sfc_flow_parse_nvgre;
82
83 typedef int (sfc_flow_spec_set_vals)(struct sfc_flow_spec *spec,
84                                      unsigned int filters_count_for_one_val,
85                                      struct rte_flow_error *error);
86
87 typedef boolean_t (sfc_flow_spec_check)(efx_filter_match_flags_t match,
88                                         efx_filter_spec_t *spec,
89                                         struct sfc_filter *filter);
90
91 struct sfc_flow_copy_flag {
92         /* EFX filter specification match flag */
93         efx_filter_match_flags_t flag;
94         /* Number of values of corresponding field */
95         unsigned int vals_count;
96         /* Function to set values in specifications */
97         sfc_flow_spec_set_vals *set_vals;
98         /*
99          * Function to check that the specification is suitable
100          * for adding this match flag
101          */
102         sfc_flow_spec_check *spec_check;
103 };
104
105 static sfc_flow_spec_set_vals sfc_flow_set_unknown_dst_flags;
106 static sfc_flow_spec_check sfc_flow_check_unknown_dst_flags;
107 static sfc_flow_spec_set_vals sfc_flow_set_ethertypes;
108 static sfc_flow_spec_set_vals sfc_flow_set_ifrm_unknown_dst_flags;
109 static sfc_flow_spec_check sfc_flow_check_ifrm_unknown_dst_flags;
110 static sfc_flow_spec_set_vals sfc_flow_set_outer_vid_flag;
111 static sfc_flow_spec_check sfc_flow_check_outer_vid_flag;
112
113 static boolean_t
114 sfc_flow_is_zero(const uint8_t *buf, unsigned int size)
115 {
116         uint8_t sum = 0;
117         unsigned int i;
118
119         for (i = 0; i < size; i++)
120                 sum |= buf[i];
121
122         return (sum == 0) ? B_TRUE : B_FALSE;
123 }
124
125 /*
126  * Validate item and prepare structures spec and mask for parsing
127  */
128 int
129 sfc_flow_parse_init(const struct rte_flow_item *item,
130                     const void **spec_ptr,
131                     const void **mask_ptr,
132                     const void *supp_mask,
133                     const void *def_mask,
134                     unsigned int size,
135                     struct rte_flow_error *error)
136 {
137         const uint8_t *spec;
138         const uint8_t *mask;
139         const uint8_t *last;
140         uint8_t supp;
141         unsigned int i;
142
143         if (item == NULL) {
144                 rte_flow_error_set(error, EINVAL,
145                                    RTE_FLOW_ERROR_TYPE_ITEM, NULL,
146                                    "NULL item");
147                 return -rte_errno;
148         }
149
150         if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) {
151                 rte_flow_error_set(error, EINVAL,
152                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
153                                    "Mask or last is set without spec");
154                 return -rte_errno;
155         }
156
157         /*
158          * If "mask" is not set, default mask is used,
159          * but if default mask is NULL, "mask" should be set
160          */
161         if (item->mask == NULL) {
162                 if (def_mask == NULL) {
163                         rte_flow_error_set(error, EINVAL,
164                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
165                                 "Mask should be specified");
166                         return -rte_errno;
167                 }
168
169                 mask = def_mask;
170         } else {
171                 mask = item->mask;
172         }
173
174         spec = item->spec;
175         last = item->last;
176
177         if (spec == NULL)
178                 goto exit;
179
180         /*
181          * If field values in "last" are either 0 or equal to the corresponding
182          * values in "spec" then they are ignored
183          */
184         if (last != NULL &&
185             !sfc_flow_is_zero(last, size) &&
186             memcmp(last, spec, size) != 0) {
187                 rte_flow_error_set(error, ENOTSUP,
188                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
189                                    "Ranging is not supported");
190                 return -rte_errno;
191         }
192
193         if (supp_mask == NULL) {
194                 rte_flow_error_set(error, EINVAL,
195                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
196                         "Supported mask for item should be specified");
197                 return -rte_errno;
198         }
199
200         /* Check that mask does not ask for more match than supp_mask */
201         for (i = 0; i < size; i++) {
202                 supp = ((const uint8_t *)supp_mask)[i];
203
204                 if (~supp & mask[i]) {
205                         rte_flow_error_set(error, ENOTSUP,
206                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
207                                            "Item's field is not supported");
208                         return -rte_errno;
209                 }
210         }
211
212 exit:
213         *spec_ptr = spec;
214         *mask_ptr = mask;
215         return 0;
216 }
217
218 /*
219  * Protocol parsers.
220  * Masking is not supported, so masks in items should be either
221  * full or empty (zeroed) and set only for supported fields which
222  * are specified in the supp_mask.
223  */
224
225 static int
226 sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item,
227                     __rte_unused struct sfc_flow_parse_ctx *parse_ctx,
228                     __rte_unused struct rte_flow_error *error)
229 {
230         return 0;
231 }
232
233 /**
234  * Convert Ethernet item to EFX filter specification.
235  *
236  * @param item[in]
237  *   Item specification. Outer frame specification may only comprise
238  *   source/destination addresses and Ethertype field.
239  *   Inner frame specification may contain destination address only.
240  *   There is support for individual/group mask as well as for empty and full.
241  *   If the mask is NULL, default mask will be used. Ranging is not supported.
242  * @param efx_spec[in, out]
243  *   EFX filter specification to update.
244  * @param[out] error
245  *   Perform verbose error reporting if not NULL.
246  */
247 static int
248 sfc_flow_parse_eth(const struct rte_flow_item *item,
249                    struct sfc_flow_parse_ctx *parse_ctx,
250                    struct rte_flow_error *error)
251 {
252         int rc;
253         efx_filter_spec_t *efx_spec = parse_ctx->filter;
254         const struct rte_flow_item_eth *spec = NULL;
255         const struct rte_flow_item_eth *mask = NULL;
256         const struct rte_flow_item_eth supp_mask = {
257                 .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
258                 .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
259                 .type = 0xffff,
260         };
261         const struct rte_flow_item_eth ifrm_supp_mask = {
262                 .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
263         };
264         const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = {
265                 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
266         };
267         const struct rte_flow_item_eth *supp_mask_p;
268         const struct rte_flow_item_eth *def_mask_p;
269         uint8_t *loc_mac = NULL;
270         boolean_t is_ifrm = (efx_spec->efs_encap_type !=
271                 EFX_TUNNEL_PROTOCOL_NONE);
272
273         if (is_ifrm) {
274                 supp_mask_p = &ifrm_supp_mask;
275                 def_mask_p = &ifrm_supp_mask;
276                 loc_mac = efx_spec->efs_ifrm_loc_mac;
277         } else {
278                 supp_mask_p = &supp_mask;
279                 def_mask_p = &rte_flow_item_eth_mask;
280                 loc_mac = efx_spec->efs_loc_mac;
281         }
282
283         rc = sfc_flow_parse_init(item,
284                                  (const void **)&spec,
285                                  (const void **)&mask,
286                                  supp_mask_p, def_mask_p,
287                                  sizeof(struct rte_flow_item_eth),
288                                  error);
289         if (rc != 0)
290                 return rc;
291
292         /* If "spec" is not set, could be any Ethernet */
293         if (spec == NULL)
294                 return 0;
295
296         if (rte_is_same_ether_addr(&mask->dst, &supp_mask.dst)) {
297                 efx_spec->efs_match_flags |= is_ifrm ?
298                         EFX_FILTER_MATCH_IFRM_LOC_MAC :
299                         EFX_FILTER_MATCH_LOC_MAC;
300                 rte_memcpy(loc_mac, spec->dst.addr_bytes,
301                            EFX_MAC_ADDR_LEN);
302         } else if (memcmp(mask->dst.addr_bytes, ig_mask,
303                           EFX_MAC_ADDR_LEN) == 0) {
304                 if (rte_is_unicast_ether_addr(&spec->dst))
305                         efx_spec->efs_match_flags |= is_ifrm ?
306                                 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST :
307                                 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
308                 else
309                         efx_spec->efs_match_flags |= is_ifrm ?
310                                 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST :
311                                 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
312         } else if (!rte_is_zero_ether_addr(&mask->dst)) {
313                 goto fail_bad_mask;
314         }
315
316         /*
317          * ifrm_supp_mask ensures that the source address and
318          * ethertype masks are equal to zero in inner frame,
319          * so these fields are filled in only for the outer frame
320          */
321         if (rte_is_same_ether_addr(&mask->src, &supp_mask.src)) {
322                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC;
323                 rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes,
324                            EFX_MAC_ADDR_LEN);
325         } else if (!rte_is_zero_ether_addr(&mask->src)) {
326                 goto fail_bad_mask;
327         }
328
329         /*
330          * Ether type is in big-endian byte order in item and
331          * in little-endian in efx_spec, so byte swap is used
332          */
333         if (mask->type == supp_mask.type) {
334                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
335                 efx_spec->efs_ether_type = rte_bswap16(spec->type);
336         } else if (mask->type != 0) {
337                 goto fail_bad_mask;
338         }
339
340         return 0;
341
342 fail_bad_mask:
343         rte_flow_error_set(error, EINVAL,
344                            RTE_FLOW_ERROR_TYPE_ITEM, item,
345                            "Bad mask in the ETH pattern item");
346         return -rte_errno;
347 }
348
349 /**
350  * Convert VLAN item to EFX filter specification.
351  *
352  * @param item[in]
353  *   Item specification. Only VID field is supported.
354  *   The mask can not be NULL. Ranging is not supported.
355  * @param efx_spec[in, out]
356  *   EFX filter specification to update.
357  * @param[out] error
358  *   Perform verbose error reporting if not NULL.
359  */
360 static int
361 sfc_flow_parse_vlan(const struct rte_flow_item *item,
362                     struct sfc_flow_parse_ctx *parse_ctx,
363                     struct rte_flow_error *error)
364 {
365         int rc;
366         uint16_t vid;
367         efx_filter_spec_t *efx_spec = parse_ctx->filter;
368         const struct rte_flow_item_vlan *spec = NULL;
369         const struct rte_flow_item_vlan *mask = NULL;
370         const struct rte_flow_item_vlan supp_mask = {
371                 .tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX),
372                 .inner_type = RTE_BE16(0xffff),
373         };
374
375         rc = sfc_flow_parse_init(item,
376                                  (const void **)&spec,
377                                  (const void **)&mask,
378                                  &supp_mask,
379                                  NULL,
380                                  sizeof(struct rte_flow_item_vlan),
381                                  error);
382         if (rc != 0)
383                 return rc;
384
385         /*
386          * VID is in big-endian byte order in item and
387          * in little-endian in efx_spec, so byte swap is used.
388          * If two VLAN items are included, the first matches
389          * the outer tag and the next matches the inner tag.
390          */
391         if (mask->tci == supp_mask.tci) {
392                 /* Apply mask to keep VID only */
393                 vid = rte_bswap16(spec->tci & mask->tci);
394
395                 if (!(efx_spec->efs_match_flags &
396                       EFX_FILTER_MATCH_OUTER_VID)) {
397                         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
398                         efx_spec->efs_outer_vid = vid;
399                 } else if (!(efx_spec->efs_match_flags &
400                              EFX_FILTER_MATCH_INNER_VID)) {
401                         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID;
402                         efx_spec->efs_inner_vid = vid;
403                 } else {
404                         rte_flow_error_set(error, EINVAL,
405                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
406                                            "More than two VLAN items");
407                         return -rte_errno;
408                 }
409         } else {
410                 rte_flow_error_set(error, EINVAL,
411                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
412                                    "VLAN ID in TCI match is required");
413                 return -rte_errno;
414         }
415
416         if (efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE) {
417                 rte_flow_error_set(error, EINVAL,
418                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
419                                    "VLAN TPID matching is not supported");
420                 return -rte_errno;
421         }
422         if (mask->inner_type == supp_mask.inner_type) {
423                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
424                 efx_spec->efs_ether_type = rte_bswap16(spec->inner_type);
425         } else if (mask->inner_type) {
426                 rte_flow_error_set(error, EINVAL,
427                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
428                                    "Bad mask for VLAN inner_type");
429                 return -rte_errno;
430         }
431
432         return 0;
433 }
434
435 /**
436  * Convert IPv4 item to EFX filter specification.
437  *
438  * @param item[in]
439  *   Item specification. Only source and destination addresses and
440  *   protocol fields are supported. If the mask is NULL, default
441  *   mask will be used. Ranging is not supported.
442  * @param efx_spec[in, out]
443  *   EFX filter specification to update.
444  * @param[out] error
445  *   Perform verbose error reporting if not NULL.
446  */
447 static int
448 sfc_flow_parse_ipv4(const struct rte_flow_item *item,
449                     struct sfc_flow_parse_ctx *parse_ctx,
450                     struct rte_flow_error *error)
451 {
452         int rc;
453         efx_filter_spec_t *efx_spec = parse_ctx->filter;
454         const struct rte_flow_item_ipv4 *spec = NULL;
455         const struct rte_flow_item_ipv4 *mask = NULL;
456         const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4);
457         const struct rte_flow_item_ipv4 supp_mask = {
458                 .hdr = {
459                         .src_addr = 0xffffffff,
460                         .dst_addr = 0xffffffff,
461                         .next_proto_id = 0xff,
462                 }
463         };
464
465         rc = sfc_flow_parse_init(item,
466                                  (const void **)&spec,
467                                  (const void **)&mask,
468                                  &supp_mask,
469                                  &rte_flow_item_ipv4_mask,
470                                  sizeof(struct rte_flow_item_ipv4),
471                                  error);
472         if (rc != 0)
473                 return rc;
474
475         /*
476          * Filtering by IPv4 source and destination addresses requires
477          * the appropriate ETHER_TYPE in hardware filters
478          */
479         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
480                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
481                 efx_spec->efs_ether_type = ether_type_ipv4;
482         } else if (efx_spec->efs_ether_type != ether_type_ipv4) {
483                 rte_flow_error_set(error, EINVAL,
484                         RTE_FLOW_ERROR_TYPE_ITEM, item,
485                         "Ethertype in pattern with IPV4 item should be appropriate");
486                 return -rte_errno;
487         }
488
489         if (spec == NULL)
490                 return 0;
491
492         /*
493          * IPv4 addresses are in big-endian byte order in item and in
494          * efx_spec
495          */
496         if (mask->hdr.src_addr == supp_mask.hdr.src_addr) {
497                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
498                 efx_spec->efs_rem_host.eo_u32[0] = spec->hdr.src_addr;
499         } else if (mask->hdr.src_addr != 0) {
500                 goto fail_bad_mask;
501         }
502
503         if (mask->hdr.dst_addr == supp_mask.hdr.dst_addr) {
504                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
505                 efx_spec->efs_loc_host.eo_u32[0] = spec->hdr.dst_addr;
506         } else if (mask->hdr.dst_addr != 0) {
507                 goto fail_bad_mask;
508         }
509
510         if (mask->hdr.next_proto_id == supp_mask.hdr.next_proto_id) {
511                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
512                 efx_spec->efs_ip_proto = spec->hdr.next_proto_id;
513         } else if (mask->hdr.next_proto_id != 0) {
514                 goto fail_bad_mask;
515         }
516
517         return 0;
518
519 fail_bad_mask:
520         rte_flow_error_set(error, EINVAL,
521                            RTE_FLOW_ERROR_TYPE_ITEM, item,
522                            "Bad mask in the IPV4 pattern item");
523         return -rte_errno;
524 }
525
526 /**
527  * Convert IPv6 item to EFX filter specification.
528  *
529  * @param item[in]
530  *   Item specification. Only source and destination addresses and
531  *   next header fields are supported. If the mask is NULL, default
532  *   mask will be used. Ranging is not supported.
533  * @param efx_spec[in, out]
534  *   EFX filter specification to update.
535  * @param[out] error
536  *   Perform verbose error reporting if not NULL.
537  */
538 static int
539 sfc_flow_parse_ipv6(const struct rte_flow_item *item,
540                     struct sfc_flow_parse_ctx *parse_ctx,
541                     struct rte_flow_error *error)
542 {
543         int rc;
544         efx_filter_spec_t *efx_spec = parse_ctx->filter;
545         const struct rte_flow_item_ipv6 *spec = NULL;
546         const struct rte_flow_item_ipv6 *mask = NULL;
547         const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6);
548         const struct rte_flow_item_ipv6 supp_mask = {
549                 .hdr = {
550                         .src_addr = { 0xff, 0xff, 0xff, 0xff,
551                                       0xff, 0xff, 0xff, 0xff,
552                                       0xff, 0xff, 0xff, 0xff,
553                                       0xff, 0xff, 0xff, 0xff },
554                         .dst_addr = { 0xff, 0xff, 0xff, 0xff,
555                                       0xff, 0xff, 0xff, 0xff,
556                                       0xff, 0xff, 0xff, 0xff,
557                                       0xff, 0xff, 0xff, 0xff },
558                         .proto = 0xff,
559                 }
560         };
561
562         rc = sfc_flow_parse_init(item,
563                                  (const void **)&spec,
564                                  (const void **)&mask,
565                                  &supp_mask,
566                                  &rte_flow_item_ipv6_mask,
567                                  sizeof(struct rte_flow_item_ipv6),
568                                  error);
569         if (rc != 0)
570                 return rc;
571
572         /*
573          * Filtering by IPv6 source and destination addresses requires
574          * the appropriate ETHER_TYPE in hardware filters
575          */
576         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
577                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
578                 efx_spec->efs_ether_type = ether_type_ipv6;
579         } else if (efx_spec->efs_ether_type != ether_type_ipv6) {
580                 rte_flow_error_set(error, EINVAL,
581                         RTE_FLOW_ERROR_TYPE_ITEM, item,
582                         "Ethertype in pattern with IPV6 item should be appropriate");
583                 return -rte_errno;
584         }
585
586         if (spec == NULL)
587                 return 0;
588
589         /*
590          * IPv6 addresses are in big-endian byte order in item and in
591          * efx_spec
592          */
593         if (memcmp(mask->hdr.src_addr, supp_mask.hdr.src_addr,
594                    sizeof(mask->hdr.src_addr)) == 0) {
595                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
596
597                 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) !=
598                                  sizeof(spec->hdr.src_addr));
599                 rte_memcpy(&efx_spec->efs_rem_host, spec->hdr.src_addr,
600                            sizeof(efx_spec->efs_rem_host));
601         } else if (!sfc_flow_is_zero(mask->hdr.src_addr,
602                                      sizeof(mask->hdr.src_addr))) {
603                 goto fail_bad_mask;
604         }
605
606         if (memcmp(mask->hdr.dst_addr, supp_mask.hdr.dst_addr,
607                    sizeof(mask->hdr.dst_addr)) == 0) {
608                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
609
610                 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) !=
611                                  sizeof(spec->hdr.dst_addr));
612                 rte_memcpy(&efx_spec->efs_loc_host, spec->hdr.dst_addr,
613                            sizeof(efx_spec->efs_loc_host));
614         } else if (!sfc_flow_is_zero(mask->hdr.dst_addr,
615                                      sizeof(mask->hdr.dst_addr))) {
616                 goto fail_bad_mask;
617         }
618
619         if (mask->hdr.proto == supp_mask.hdr.proto) {
620                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
621                 efx_spec->efs_ip_proto = spec->hdr.proto;
622         } else if (mask->hdr.proto != 0) {
623                 goto fail_bad_mask;
624         }
625
626         return 0;
627
628 fail_bad_mask:
629         rte_flow_error_set(error, EINVAL,
630                            RTE_FLOW_ERROR_TYPE_ITEM, item,
631                            "Bad mask in the IPV6 pattern item");
632         return -rte_errno;
633 }
634
635 /**
636  * Convert TCP item to EFX filter specification.
637  *
638  * @param item[in]
639  *   Item specification. Only source and destination ports fields
640  *   are supported. If the mask is NULL, default mask will be used.
641  *   Ranging is not supported.
642  * @param efx_spec[in, out]
643  *   EFX filter specification to update.
644  * @param[out] error
645  *   Perform verbose error reporting if not NULL.
646  */
647 static int
648 sfc_flow_parse_tcp(const struct rte_flow_item *item,
649                    struct sfc_flow_parse_ctx *parse_ctx,
650                    struct rte_flow_error *error)
651 {
652         int rc;
653         efx_filter_spec_t *efx_spec = parse_ctx->filter;
654         const struct rte_flow_item_tcp *spec = NULL;
655         const struct rte_flow_item_tcp *mask = NULL;
656         const struct rte_flow_item_tcp supp_mask = {
657                 .hdr = {
658                         .src_port = 0xffff,
659                         .dst_port = 0xffff,
660                 }
661         };
662
663         rc = sfc_flow_parse_init(item,
664                                  (const void **)&spec,
665                                  (const void **)&mask,
666                                  &supp_mask,
667                                  &rte_flow_item_tcp_mask,
668                                  sizeof(struct rte_flow_item_tcp),
669                                  error);
670         if (rc != 0)
671                 return rc;
672
673         /*
674          * Filtering by TCP source and destination ports requires
675          * the appropriate IP_PROTO in hardware filters
676          */
677         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
678                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
679                 efx_spec->efs_ip_proto = EFX_IPPROTO_TCP;
680         } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_TCP) {
681                 rte_flow_error_set(error, EINVAL,
682                         RTE_FLOW_ERROR_TYPE_ITEM, item,
683                         "IP proto in pattern with TCP item should be appropriate");
684                 return -rte_errno;
685         }
686
687         if (spec == NULL)
688                 return 0;
689
690         /*
691          * Source and destination ports are in big-endian byte order in item and
692          * in little-endian in efx_spec, so byte swap is used
693          */
694         if (mask->hdr.src_port == supp_mask.hdr.src_port) {
695                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
696                 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
697         } else if (mask->hdr.src_port != 0) {
698                 goto fail_bad_mask;
699         }
700
701         if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
702                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
703                 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
704         } else if (mask->hdr.dst_port != 0) {
705                 goto fail_bad_mask;
706         }
707
708         return 0;
709
710 fail_bad_mask:
711         rte_flow_error_set(error, EINVAL,
712                            RTE_FLOW_ERROR_TYPE_ITEM, item,
713                            "Bad mask in the TCP pattern item");
714         return -rte_errno;
715 }
716
717 /**
718  * Convert UDP item to EFX filter specification.
719  *
720  * @param item[in]
721  *   Item specification. Only source and destination ports fields
722  *   are supported. If the mask is NULL, default mask will be used.
723  *   Ranging is not supported.
724  * @param efx_spec[in, out]
725  *   EFX filter specification to update.
726  * @param[out] error
727  *   Perform verbose error reporting if not NULL.
728  */
729 static int
730 sfc_flow_parse_udp(const struct rte_flow_item *item,
731                    struct sfc_flow_parse_ctx *parse_ctx,
732                    struct rte_flow_error *error)
733 {
734         int rc;
735         efx_filter_spec_t *efx_spec = parse_ctx->filter;
736         const struct rte_flow_item_udp *spec = NULL;
737         const struct rte_flow_item_udp *mask = NULL;
738         const struct rte_flow_item_udp supp_mask = {
739                 .hdr = {
740                         .src_port = 0xffff,
741                         .dst_port = 0xffff,
742                 }
743         };
744
745         rc = sfc_flow_parse_init(item,
746                                  (const void **)&spec,
747                                  (const void **)&mask,
748                                  &supp_mask,
749                                  &rte_flow_item_udp_mask,
750                                  sizeof(struct rte_flow_item_udp),
751                                  error);
752         if (rc != 0)
753                 return rc;
754
755         /*
756          * Filtering by UDP source and destination ports requires
757          * the appropriate IP_PROTO in hardware filters
758          */
759         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
760                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
761                 efx_spec->efs_ip_proto = EFX_IPPROTO_UDP;
762         } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_UDP) {
763                 rte_flow_error_set(error, EINVAL,
764                         RTE_FLOW_ERROR_TYPE_ITEM, item,
765                         "IP proto in pattern with UDP item should be appropriate");
766                 return -rte_errno;
767         }
768
769         if (spec == NULL)
770                 return 0;
771
772         /*
773          * Source and destination ports are in big-endian byte order in item and
774          * in little-endian in efx_spec, so byte swap is used
775          */
776         if (mask->hdr.src_port == supp_mask.hdr.src_port) {
777                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
778                 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
779         } else if (mask->hdr.src_port != 0) {
780                 goto fail_bad_mask;
781         }
782
783         if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
784                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
785                 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
786         } else if (mask->hdr.dst_port != 0) {
787                 goto fail_bad_mask;
788         }
789
790         return 0;
791
792 fail_bad_mask:
793         rte_flow_error_set(error, EINVAL,
794                            RTE_FLOW_ERROR_TYPE_ITEM, item,
795                            "Bad mask in the UDP pattern item");
796         return -rte_errno;
797 }
798
799 /*
800  * Filters for encapsulated packets match based on the EtherType and IP
801  * protocol in the outer frame.
802  */
803 static int
804 sfc_flow_set_match_flags_for_encap_pkts(const struct rte_flow_item *item,
805                                         efx_filter_spec_t *efx_spec,
806                                         uint8_t ip_proto,
807                                         struct rte_flow_error *error)
808 {
809         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
810                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
811                 efx_spec->efs_ip_proto = ip_proto;
812         } else if (efx_spec->efs_ip_proto != ip_proto) {
813                 switch (ip_proto) {
814                 case EFX_IPPROTO_UDP:
815                         rte_flow_error_set(error, EINVAL,
816                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
817                                 "Outer IP header protocol must be UDP "
818                                 "in VxLAN/GENEVE pattern");
819                         return -rte_errno;
820
821                 case EFX_IPPROTO_GRE:
822                         rte_flow_error_set(error, EINVAL,
823                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
824                                 "Outer IP header protocol must be GRE "
825                                 "in NVGRE pattern");
826                         return -rte_errno;
827
828                 default:
829                         rte_flow_error_set(error, EINVAL,
830                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
831                                 "Only VxLAN/GENEVE/NVGRE tunneling patterns "
832                                 "are supported");
833                         return -rte_errno;
834                 }
835         }
836
837         if (efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE &&
838             efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV4 &&
839             efx_spec->efs_ether_type != EFX_ETHER_TYPE_IPV6) {
840                 rte_flow_error_set(error, EINVAL,
841                         RTE_FLOW_ERROR_TYPE_ITEM, item,
842                         "Outer frame EtherType in pattern with tunneling "
843                         "must be IPv4 or IPv6");
844                 return -rte_errno;
845         }
846
847         return 0;
848 }
849
850 static int
851 sfc_flow_set_efx_spec_vni_or_vsid(efx_filter_spec_t *efx_spec,
852                                   const uint8_t *vni_or_vsid_val,
853                                   const uint8_t *vni_or_vsid_mask,
854                                   const struct rte_flow_item *item,
855                                   struct rte_flow_error *error)
856 {
857         const uint8_t vni_or_vsid_full_mask[EFX_VNI_OR_VSID_LEN] = {
858                 0xff, 0xff, 0xff
859         };
860
861         if (memcmp(vni_or_vsid_mask, vni_or_vsid_full_mask,
862                    EFX_VNI_OR_VSID_LEN) == 0) {
863                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_VNI_OR_VSID;
864                 rte_memcpy(efx_spec->efs_vni_or_vsid, vni_or_vsid_val,
865                            EFX_VNI_OR_VSID_LEN);
866         } else if (!sfc_flow_is_zero(vni_or_vsid_mask, EFX_VNI_OR_VSID_LEN)) {
867                 rte_flow_error_set(error, EINVAL,
868                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
869                                    "Unsupported VNI/VSID mask");
870                 return -rte_errno;
871         }
872
873         return 0;
874 }
875
876 /**
877  * Convert VXLAN item to EFX filter specification.
878  *
879  * @param item[in]
880  *   Item specification. Only VXLAN network identifier field is supported.
881  *   If the mask is NULL, default mask will be used.
882  *   Ranging is not supported.
883  * @param efx_spec[in, out]
884  *   EFX filter specification to update.
885  * @param[out] error
886  *   Perform verbose error reporting if not NULL.
887  */
888 static int
889 sfc_flow_parse_vxlan(const struct rte_flow_item *item,
890                      struct sfc_flow_parse_ctx *parse_ctx,
891                      struct rte_flow_error *error)
892 {
893         int rc;
894         efx_filter_spec_t *efx_spec = parse_ctx->filter;
895         const struct rte_flow_item_vxlan *spec = NULL;
896         const struct rte_flow_item_vxlan *mask = NULL;
897         const struct rte_flow_item_vxlan supp_mask = {
898                 .vni = { 0xff, 0xff, 0xff }
899         };
900
901         rc = sfc_flow_parse_init(item,
902                                  (const void **)&spec,
903                                  (const void **)&mask,
904                                  &supp_mask,
905                                  &rte_flow_item_vxlan_mask,
906                                  sizeof(struct rte_flow_item_vxlan),
907                                  error);
908         if (rc != 0)
909                 return rc;
910
911         rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
912                                                      EFX_IPPROTO_UDP, error);
913         if (rc != 0)
914                 return rc;
915
916         efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
917         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
918
919         if (spec == NULL)
920                 return 0;
921
922         rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni,
923                                                mask->vni, item, error);
924
925         return rc;
926 }
927
928 /**
929  * Convert GENEVE item to EFX filter specification.
930  *
931  * @param item[in]
932  *   Item specification. Only Virtual Network Identifier and protocol type
933  *   fields are supported. But protocol type can be only Ethernet (0x6558).
934  *   If the mask is NULL, default mask will be used.
935  *   Ranging is not supported.
936  * @param efx_spec[in, out]
937  *   EFX filter specification to update.
938  * @param[out] error
939  *   Perform verbose error reporting if not NULL.
940  */
941 static int
942 sfc_flow_parse_geneve(const struct rte_flow_item *item,
943                       struct sfc_flow_parse_ctx *parse_ctx,
944                       struct rte_flow_error *error)
945 {
946         int rc;
947         efx_filter_spec_t *efx_spec = parse_ctx->filter;
948         const struct rte_flow_item_geneve *spec = NULL;
949         const struct rte_flow_item_geneve *mask = NULL;
950         const struct rte_flow_item_geneve supp_mask = {
951                 .protocol = RTE_BE16(0xffff),
952                 .vni = { 0xff, 0xff, 0xff }
953         };
954
955         rc = sfc_flow_parse_init(item,
956                                  (const void **)&spec,
957                                  (const void **)&mask,
958                                  &supp_mask,
959                                  &rte_flow_item_geneve_mask,
960                                  sizeof(struct rte_flow_item_geneve),
961                                  error);
962         if (rc != 0)
963                 return rc;
964
965         rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
966                                                      EFX_IPPROTO_UDP, error);
967         if (rc != 0)
968                 return rc;
969
970         efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_GENEVE;
971         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
972
973         if (spec == NULL)
974                 return 0;
975
976         if (mask->protocol == supp_mask.protocol) {
977                 if (spec->protocol != rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB)) {
978                         rte_flow_error_set(error, EINVAL,
979                                 RTE_FLOW_ERROR_TYPE_ITEM, item,
980                                 "GENEVE encap. protocol must be Ethernet "
981                                 "(0x6558) in the GENEVE pattern item");
982                         return -rte_errno;
983                 }
984         } else if (mask->protocol != 0) {
985                 rte_flow_error_set(error, EINVAL,
986                         RTE_FLOW_ERROR_TYPE_ITEM, item,
987                         "Unsupported mask for GENEVE encap. protocol");
988                 return -rte_errno;
989         }
990
991         rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->vni,
992                                                mask->vni, item, error);
993
994         return rc;
995 }
996
997 /**
998  * Convert NVGRE item to EFX filter specification.
999  *
1000  * @param item[in]
1001  *   Item specification. Only virtual subnet ID field is supported.
1002  *   If the mask is NULL, default mask will be used.
1003  *   Ranging is not supported.
1004  * @param efx_spec[in, out]
1005  *   EFX filter specification to update.
1006  * @param[out] error
1007  *   Perform verbose error reporting if not NULL.
1008  */
1009 static int
1010 sfc_flow_parse_nvgre(const struct rte_flow_item *item,
1011                      struct sfc_flow_parse_ctx *parse_ctx,
1012                      struct rte_flow_error *error)
1013 {
1014         int rc;
1015         efx_filter_spec_t *efx_spec = parse_ctx->filter;
1016         const struct rte_flow_item_nvgre *spec = NULL;
1017         const struct rte_flow_item_nvgre *mask = NULL;
1018         const struct rte_flow_item_nvgre supp_mask = {
1019                 .tni = { 0xff, 0xff, 0xff }
1020         };
1021
1022         rc = sfc_flow_parse_init(item,
1023                                  (const void **)&spec,
1024                                  (const void **)&mask,
1025                                  &supp_mask,
1026                                  &rte_flow_item_nvgre_mask,
1027                                  sizeof(struct rte_flow_item_nvgre),
1028                                  error);
1029         if (rc != 0)
1030                 return rc;
1031
1032         rc = sfc_flow_set_match_flags_for_encap_pkts(item, efx_spec,
1033                                                      EFX_IPPROTO_GRE, error);
1034         if (rc != 0)
1035                 return rc;
1036
1037         efx_spec->efs_encap_type = EFX_TUNNEL_PROTOCOL_NVGRE;
1038         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ENCAP_TYPE;
1039
1040         if (spec == NULL)
1041                 return 0;
1042
1043         rc = sfc_flow_set_efx_spec_vni_or_vsid(efx_spec, spec->tni,
1044                                                mask->tni, item, error);
1045
1046         return rc;
1047 }
1048
1049 static const struct sfc_flow_item sfc_flow_items[] = {
1050         {
1051                 .type = RTE_FLOW_ITEM_TYPE_VOID,
1052                 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
1053                 .layer = SFC_FLOW_ITEM_ANY_LAYER,
1054                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1055                 .parse = sfc_flow_parse_void,
1056         },
1057         {
1058                 .type = RTE_FLOW_ITEM_TYPE_ETH,
1059                 .prev_layer = SFC_FLOW_ITEM_START_LAYER,
1060                 .layer = SFC_FLOW_ITEM_L2,
1061                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1062                 .parse = sfc_flow_parse_eth,
1063         },
1064         {
1065                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
1066                 .prev_layer = SFC_FLOW_ITEM_L2,
1067                 .layer = SFC_FLOW_ITEM_L2,
1068                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1069                 .parse = sfc_flow_parse_vlan,
1070         },
1071         {
1072                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
1073                 .prev_layer = SFC_FLOW_ITEM_L2,
1074                 .layer = SFC_FLOW_ITEM_L3,
1075                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1076                 .parse = sfc_flow_parse_ipv4,
1077         },
1078         {
1079                 .type = RTE_FLOW_ITEM_TYPE_IPV6,
1080                 .prev_layer = SFC_FLOW_ITEM_L2,
1081                 .layer = SFC_FLOW_ITEM_L3,
1082                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1083                 .parse = sfc_flow_parse_ipv6,
1084         },
1085         {
1086                 .type = RTE_FLOW_ITEM_TYPE_TCP,
1087                 .prev_layer = SFC_FLOW_ITEM_L3,
1088                 .layer = SFC_FLOW_ITEM_L4,
1089                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1090                 .parse = sfc_flow_parse_tcp,
1091         },
1092         {
1093                 .type = RTE_FLOW_ITEM_TYPE_UDP,
1094                 .prev_layer = SFC_FLOW_ITEM_L3,
1095                 .layer = SFC_FLOW_ITEM_L4,
1096                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1097                 .parse = sfc_flow_parse_udp,
1098         },
1099         {
1100                 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
1101                 .prev_layer = SFC_FLOW_ITEM_L4,
1102                 .layer = SFC_FLOW_ITEM_START_LAYER,
1103                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1104                 .parse = sfc_flow_parse_vxlan,
1105         },
1106         {
1107                 .type = RTE_FLOW_ITEM_TYPE_GENEVE,
1108                 .prev_layer = SFC_FLOW_ITEM_L4,
1109                 .layer = SFC_FLOW_ITEM_START_LAYER,
1110                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1111                 .parse = sfc_flow_parse_geneve,
1112         },
1113         {
1114                 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
1115                 .prev_layer = SFC_FLOW_ITEM_L3,
1116                 .layer = SFC_FLOW_ITEM_START_LAYER,
1117                 .ctx_type = SFC_FLOW_PARSE_CTX_FILTER,
1118                 .parse = sfc_flow_parse_nvgre,
1119         },
1120 };
1121
1122 /*
1123  * Protocol-independent flow API support
1124  */
1125 static int
1126 sfc_flow_parse_attr(const struct rte_flow_attr *attr,
1127                     struct rte_flow *flow,
1128                     struct rte_flow_error *error)
1129 {
1130         struct sfc_flow_spec *spec = &flow->spec;
1131         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1132
1133         if (attr == NULL) {
1134                 rte_flow_error_set(error, EINVAL,
1135                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
1136                                    "NULL attribute");
1137                 return -rte_errno;
1138         }
1139         if (attr->group != 0) {
1140                 rte_flow_error_set(error, ENOTSUP,
1141                                    RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr,
1142                                    "Groups are not supported");
1143                 return -rte_errno;
1144         }
1145         if (attr->egress != 0) {
1146                 rte_flow_error_set(error, ENOTSUP,
1147                                    RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr,
1148                                    "Egress is not supported");
1149                 return -rte_errno;
1150         }
1151         if (attr->ingress == 0) {
1152                 rte_flow_error_set(error, ENOTSUP,
1153                                    RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
1154                                    "Ingress is compulsory");
1155                 return -rte_errno;
1156         }
1157         if (attr->transfer == 0) {
1158                 if (attr->priority != 0) {
1159                         rte_flow_error_set(error, ENOTSUP,
1160                                            RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
1161                                            attr, "Priorities are unsupported");
1162                         return -rte_errno;
1163                 }
1164                 spec->type = SFC_FLOW_SPEC_FILTER;
1165                 spec_filter->template.efs_flags |= EFX_FILTER_FLAG_RX;
1166                 spec_filter->template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
1167                 spec_filter->template.efs_priority = EFX_FILTER_PRI_MANUAL;
1168         } else {
1169                 rte_flow_error_set(error, ENOTSUP,
1170                                    RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, attr,
1171                                    "Transfer is not supported");
1172                 return -rte_errno;
1173         }
1174
1175         return 0;
1176 }
1177
1178 /* Get item from array sfc_flow_items */
1179 static const struct sfc_flow_item *
1180 sfc_flow_get_item(const struct sfc_flow_item *items,
1181                   unsigned int nb_items,
1182                   enum rte_flow_item_type type)
1183 {
1184         unsigned int i;
1185
1186         for (i = 0; i < nb_items; i++)
1187                 if (items[i].type == type)
1188                         return &items[i];
1189
1190         return NULL;
1191 }
1192
1193 int
1194 sfc_flow_parse_pattern(const struct sfc_flow_item *flow_items,
1195                        unsigned int nb_flow_items,
1196                        const struct rte_flow_item pattern[],
1197                        struct sfc_flow_parse_ctx *parse_ctx,
1198                        struct rte_flow_error *error)
1199 {
1200         int rc;
1201         unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER;
1202         boolean_t is_ifrm = B_FALSE;
1203         const struct sfc_flow_item *item;
1204
1205         if (pattern == NULL) {
1206                 rte_flow_error_set(error, EINVAL,
1207                                    RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
1208                                    "NULL pattern");
1209                 return -rte_errno;
1210         }
1211
1212         for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
1213                 item = sfc_flow_get_item(flow_items, nb_flow_items,
1214                                          pattern->type);
1215                 if (item == NULL) {
1216                         rte_flow_error_set(error, ENOTSUP,
1217                                            RTE_FLOW_ERROR_TYPE_ITEM, pattern,
1218                                            "Unsupported pattern item");
1219                         return -rte_errno;
1220                 }
1221
1222                 /*
1223                  * Omitting one or several protocol layers at the beginning
1224                  * of pattern is supported
1225                  */
1226                 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
1227                     prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
1228                     item->prev_layer != prev_layer) {
1229                         rte_flow_error_set(error, ENOTSUP,
1230                                            RTE_FLOW_ERROR_TYPE_ITEM, pattern,
1231                                            "Unexpected sequence of pattern items");
1232                         return -rte_errno;
1233                 }
1234
1235                 /*
1236                  * Allow only VOID and ETH pattern items in the inner frame.
1237                  * Also check that there is only one tunneling protocol.
1238                  */
1239                 switch (item->type) {
1240                 case RTE_FLOW_ITEM_TYPE_VOID:
1241                 case RTE_FLOW_ITEM_TYPE_ETH:
1242                         break;
1243
1244                 case RTE_FLOW_ITEM_TYPE_VXLAN:
1245                 case RTE_FLOW_ITEM_TYPE_GENEVE:
1246                 case RTE_FLOW_ITEM_TYPE_NVGRE:
1247                         if (is_ifrm) {
1248                                 rte_flow_error_set(error, EINVAL,
1249                                         RTE_FLOW_ERROR_TYPE_ITEM,
1250                                         pattern,
1251                                         "More than one tunneling protocol");
1252                                 return -rte_errno;
1253                         }
1254                         is_ifrm = B_TRUE;
1255                         break;
1256
1257                 default:
1258                         if (is_ifrm) {
1259                                 rte_flow_error_set(error, EINVAL,
1260                                         RTE_FLOW_ERROR_TYPE_ITEM,
1261                                         pattern,
1262                                         "There is an unsupported pattern item "
1263                                         "in the inner frame");
1264                                 return -rte_errno;
1265                         }
1266                         break;
1267                 }
1268
1269                 if (parse_ctx->type != item->ctx_type) {
1270                         rte_flow_error_set(error, EINVAL,
1271                                         RTE_FLOW_ERROR_TYPE_ITEM, pattern,
1272                                         "Parse context type mismatch");
1273                         return -rte_errno;
1274                 }
1275
1276                 rc = item->parse(pattern, parse_ctx, error);
1277                 if (rc != 0)
1278                         return rc;
1279
1280                 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER)
1281                         prev_layer = item->layer;
1282         }
1283
1284         return 0;
1285 }
1286
1287 static int
1288 sfc_flow_parse_queue(struct sfc_adapter *sa,
1289                      const struct rte_flow_action_queue *queue,
1290                      struct rte_flow *flow)
1291 {
1292         struct sfc_flow_spec *spec = &flow->spec;
1293         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1294         struct sfc_rxq *rxq;
1295
1296         if (queue->index >= sfc_sa2shared(sa)->rxq_count)
1297                 return -EINVAL;
1298
1299         rxq = &sa->rxq_ctrl[queue->index];
1300         spec_filter->template.efs_dmaq_id = (uint16_t)rxq->hw_index;
1301
1302         return 0;
1303 }
1304
1305 static int
1306 sfc_flow_parse_rss(struct sfc_adapter *sa,
1307                    const struct rte_flow_action_rss *action_rss,
1308                    struct rte_flow *flow)
1309 {
1310         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
1311         struct sfc_rss *rss = &sas->rss;
1312         unsigned int rxq_sw_index;
1313         struct sfc_rxq *rxq;
1314         unsigned int rxq_hw_index_min;
1315         unsigned int rxq_hw_index_max;
1316         efx_rx_hash_type_t efx_hash_types;
1317         const uint8_t *rss_key;
1318         struct sfc_flow_spec *spec = &flow->spec;
1319         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1320         struct sfc_flow_rss *sfc_rss_conf = &spec_filter->rss_conf;
1321         unsigned int i;
1322
1323         if (action_rss->queue_num == 0)
1324                 return -EINVAL;
1325
1326         rxq_sw_index = sfc_sa2shared(sa)->rxq_count - 1;
1327         rxq = &sa->rxq_ctrl[rxq_sw_index];
1328         rxq_hw_index_min = rxq->hw_index;
1329         rxq_hw_index_max = 0;
1330
1331         for (i = 0; i < action_rss->queue_num; ++i) {
1332                 rxq_sw_index = action_rss->queue[i];
1333
1334                 if (rxq_sw_index >= sfc_sa2shared(sa)->rxq_count)
1335                         return -EINVAL;
1336
1337                 rxq = &sa->rxq_ctrl[rxq_sw_index];
1338
1339                 if (rxq->hw_index < rxq_hw_index_min)
1340                         rxq_hw_index_min = rxq->hw_index;
1341
1342                 if (rxq->hw_index > rxq_hw_index_max)
1343                         rxq_hw_index_max = rxq->hw_index;
1344         }
1345
1346         switch (action_rss->func) {
1347         case RTE_ETH_HASH_FUNCTION_DEFAULT:
1348         case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
1349                 break;
1350         default:
1351                 return -EINVAL;
1352         }
1353
1354         if (action_rss->level)
1355                 return -EINVAL;
1356
1357         /*
1358          * Dummy RSS action with only one queue and no specific settings
1359          * for hash types and key does not require dedicated RSS context
1360          * and may be simplified to single queue action.
1361          */
1362         if (action_rss->queue_num == 1 && action_rss->types == 0 &&
1363             action_rss->key_len == 0) {
1364                 spec_filter->template.efs_dmaq_id = rxq_hw_index_min;
1365                 return 0;
1366         }
1367
1368         if (action_rss->types) {
1369                 int rc;
1370
1371                 rc = sfc_rx_hf_rte_to_efx(sa, action_rss->types,
1372                                           &efx_hash_types);
1373                 if (rc != 0)
1374                         return -rc;
1375         } else {
1376                 unsigned int i;
1377
1378                 efx_hash_types = 0;
1379                 for (i = 0; i < rss->hf_map_nb_entries; ++i)
1380                         efx_hash_types |= rss->hf_map[i].efx;
1381         }
1382
1383         if (action_rss->key_len) {
1384                 if (action_rss->key_len != sizeof(rss->key))
1385                         return -EINVAL;
1386
1387                 rss_key = action_rss->key;
1388         } else {
1389                 rss_key = rss->key;
1390         }
1391
1392         spec_filter->rss = B_TRUE;
1393
1394         sfc_rss_conf->rxq_hw_index_min = rxq_hw_index_min;
1395         sfc_rss_conf->rxq_hw_index_max = rxq_hw_index_max;
1396         sfc_rss_conf->rss_hash_types = efx_hash_types;
1397         rte_memcpy(sfc_rss_conf->rss_key, rss_key, sizeof(rss->key));
1398
1399         for (i = 0; i < RTE_DIM(sfc_rss_conf->rss_tbl); ++i) {
1400                 unsigned int nb_queues = action_rss->queue_num;
1401                 unsigned int rxq_sw_index = action_rss->queue[i % nb_queues];
1402                 struct sfc_rxq *rxq = &sa->rxq_ctrl[rxq_sw_index];
1403
1404                 sfc_rss_conf->rss_tbl[i] = rxq->hw_index - rxq_hw_index_min;
1405         }
1406
1407         return 0;
1408 }
1409
1410 static int
1411 sfc_flow_spec_flush(struct sfc_adapter *sa, struct sfc_flow_spec *spec,
1412                     unsigned int filters_count)
1413 {
1414         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1415         unsigned int i;
1416         int ret = 0;
1417
1418         for (i = 0; i < filters_count; i++) {
1419                 int rc;
1420
1421                 rc = efx_filter_remove(sa->nic, &spec_filter->filters[i]);
1422                 if (ret == 0 && rc != 0) {
1423                         sfc_err(sa, "failed to remove filter specification "
1424                                 "(rc = %d)", rc);
1425                         ret = rc;
1426                 }
1427         }
1428
1429         return ret;
1430 }
1431
1432 static int
1433 sfc_flow_spec_insert(struct sfc_adapter *sa, struct sfc_flow_spec *spec)
1434 {
1435         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1436         unsigned int i;
1437         int rc = 0;
1438
1439         for (i = 0; i < spec_filter->count; i++) {
1440                 rc = efx_filter_insert(sa->nic, &spec_filter->filters[i]);
1441                 if (rc != 0) {
1442                         sfc_flow_spec_flush(sa, spec, i);
1443                         break;
1444                 }
1445         }
1446
1447         return rc;
1448 }
1449
1450 static int
1451 sfc_flow_spec_remove(struct sfc_adapter *sa, struct sfc_flow_spec *spec)
1452 {
1453         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1454
1455         return sfc_flow_spec_flush(sa, spec, spec_filter->count);
1456 }
1457
1458 static int
1459 sfc_flow_filter_insert(struct sfc_adapter *sa,
1460                        struct rte_flow *flow)
1461 {
1462         struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
1463         struct sfc_rss *rss = &sas->rss;
1464         struct sfc_flow_spec_filter *spec_filter = &flow->spec.filter;
1465         struct sfc_flow_rss *flow_rss = &spec_filter->rss_conf;
1466         uint32_t efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
1467         unsigned int i;
1468         int rc = 0;
1469
1470         if (spec_filter->rss) {
1471                 unsigned int rss_spread = MIN(flow_rss->rxq_hw_index_max -
1472                                               flow_rss->rxq_hw_index_min + 1,
1473                                               EFX_MAXRSS);
1474
1475                 rc = efx_rx_scale_context_alloc(sa->nic,
1476                                                 EFX_RX_SCALE_EXCLUSIVE,
1477                                                 rss_spread,
1478                                                 &efs_rss_context);
1479                 if (rc != 0)
1480                         goto fail_scale_context_alloc;
1481
1482                 rc = efx_rx_scale_mode_set(sa->nic, efs_rss_context,
1483                                            rss->hash_alg,
1484                                            flow_rss->rss_hash_types, B_TRUE);
1485                 if (rc != 0)
1486                         goto fail_scale_mode_set;
1487
1488                 rc = efx_rx_scale_key_set(sa->nic, efs_rss_context,
1489                                           flow_rss->rss_key,
1490                                           sizeof(rss->key));
1491                 if (rc != 0)
1492                         goto fail_scale_key_set;
1493
1494                 /*
1495                  * At this point, fully elaborated filter specifications
1496                  * have been produced from the template. To make sure that
1497                  * RSS behaviour is consistent between them, set the same
1498                  * RSS context value everywhere.
1499                  */
1500                 for (i = 0; i < spec_filter->count; i++) {
1501                         efx_filter_spec_t *spec = &spec_filter->filters[i];
1502
1503                         spec->efs_rss_context = efs_rss_context;
1504                         spec->efs_dmaq_id = flow_rss->rxq_hw_index_min;
1505                         spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS;
1506                 }
1507         }
1508
1509         rc = sfc_flow_spec_insert(sa, &flow->spec);
1510         if (rc != 0)
1511                 goto fail_filter_insert;
1512
1513         if (spec_filter->rss) {
1514                 /*
1515                  * Scale table is set after filter insertion because
1516                  * the table entries are relative to the base RxQ ID
1517                  * and the latter is submitted to the HW by means of
1518                  * inserting a filter, so by the time of the request
1519                  * the HW knows all the information needed to verify
1520                  * the table entries, and the operation will succeed
1521                  */
1522                 rc = efx_rx_scale_tbl_set(sa->nic, efs_rss_context,
1523                                           flow_rss->rss_tbl,
1524                                           RTE_DIM(flow_rss->rss_tbl));
1525                 if (rc != 0)
1526                         goto fail_scale_tbl_set;
1527         }
1528
1529         return 0;
1530
1531 fail_scale_tbl_set:
1532         sfc_flow_spec_remove(sa, &flow->spec);
1533
1534 fail_filter_insert:
1535 fail_scale_key_set:
1536 fail_scale_mode_set:
1537         if (efs_rss_context != EFX_RSS_CONTEXT_DEFAULT)
1538                 efx_rx_scale_context_free(sa->nic, efs_rss_context);
1539
1540 fail_scale_context_alloc:
1541         return rc;
1542 }
1543
1544 static int
1545 sfc_flow_filter_remove(struct sfc_adapter *sa,
1546                        struct rte_flow *flow)
1547 {
1548         struct sfc_flow_spec_filter *spec_filter = &flow->spec.filter;
1549         int rc = 0;
1550
1551         rc = sfc_flow_spec_remove(sa, &flow->spec);
1552         if (rc != 0)
1553                 return rc;
1554
1555         if (spec_filter->rss) {
1556                 /*
1557                  * All specifications for a given flow rule have the same RSS
1558                  * context, so that RSS context value is taken from the first
1559                  * filter specification
1560                  */
1561                 efx_filter_spec_t *spec = &spec_filter->filters[0];
1562
1563                 rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
1564         }
1565
1566         return rc;
1567 }
1568
1569 static int
1570 sfc_flow_parse_mark(struct sfc_adapter *sa,
1571                     const struct rte_flow_action_mark *mark,
1572                     struct rte_flow *flow)
1573 {
1574         struct sfc_flow_spec *spec = &flow->spec;
1575         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1576         const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
1577
1578         if (mark == NULL || mark->id > encp->enc_filter_action_mark_max)
1579                 return EINVAL;
1580
1581         spec_filter->template.efs_flags |= EFX_FILTER_FLAG_ACTION_MARK;
1582         spec_filter->template.efs_mark = mark->id;
1583
1584         return 0;
1585 }
1586
1587 static int
1588 sfc_flow_parse_actions(struct sfc_adapter *sa,
1589                        const struct rte_flow_action actions[],
1590                        struct rte_flow *flow,
1591                        struct rte_flow_error *error)
1592 {
1593         int rc;
1594         struct sfc_flow_spec *spec = &flow->spec;
1595         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1596         const unsigned int dp_rx_features = sa->priv.dp_rx->features;
1597         uint32_t actions_set = 0;
1598         const uint32_t fate_actions_mask = (1UL << RTE_FLOW_ACTION_TYPE_QUEUE) |
1599                                            (1UL << RTE_FLOW_ACTION_TYPE_RSS) |
1600                                            (1UL << RTE_FLOW_ACTION_TYPE_DROP);
1601         const uint32_t mark_actions_mask = (1UL << RTE_FLOW_ACTION_TYPE_MARK) |
1602                                            (1UL << RTE_FLOW_ACTION_TYPE_FLAG);
1603
1604         if (actions == NULL) {
1605                 rte_flow_error_set(error, EINVAL,
1606                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
1607                                    "NULL actions");
1608                 return -rte_errno;
1609         }
1610
1611 #define SFC_BUILD_SET_OVERFLOW(_action, _set) \
1612         RTE_BUILD_BUG_ON(_action >= sizeof(_set) * CHAR_BIT)
1613
1614         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1615                 switch (actions->type) {
1616                 case RTE_FLOW_ACTION_TYPE_VOID:
1617                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VOID,
1618                                                actions_set);
1619                         break;
1620
1621                 case RTE_FLOW_ACTION_TYPE_QUEUE:
1622                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_QUEUE,
1623                                                actions_set);
1624                         if ((actions_set & fate_actions_mask) != 0)
1625                                 goto fail_fate_actions;
1626
1627                         rc = sfc_flow_parse_queue(sa, actions->conf, flow);
1628                         if (rc != 0) {
1629                                 rte_flow_error_set(error, EINVAL,
1630                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
1631                                         "Bad QUEUE action");
1632                                 return -rte_errno;
1633                         }
1634                         break;
1635
1636                 case RTE_FLOW_ACTION_TYPE_RSS:
1637                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_RSS,
1638                                                actions_set);
1639                         if ((actions_set & fate_actions_mask) != 0)
1640                                 goto fail_fate_actions;
1641
1642                         rc = sfc_flow_parse_rss(sa, actions->conf, flow);
1643                         if (rc != 0) {
1644                                 rte_flow_error_set(error, -rc,
1645                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
1646                                         "Bad RSS action");
1647                                 return -rte_errno;
1648                         }
1649                         break;
1650
1651                 case RTE_FLOW_ACTION_TYPE_DROP:
1652                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
1653                                                actions_set);
1654                         if ((actions_set & fate_actions_mask) != 0)
1655                                 goto fail_fate_actions;
1656
1657                         spec_filter->template.efs_dmaq_id =
1658                                 EFX_FILTER_SPEC_RX_DMAQ_ID_DROP;
1659                         break;
1660
1661                 case RTE_FLOW_ACTION_TYPE_FLAG:
1662                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
1663                                                actions_set);
1664                         if ((actions_set & mark_actions_mask) != 0)
1665                                 goto fail_actions_overlap;
1666
1667                         if ((dp_rx_features & SFC_DP_RX_FEAT_FLOW_FLAG) == 0) {
1668                                 rte_flow_error_set(error, ENOTSUP,
1669                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
1670                                         "FLAG action is not supported on the current Rx datapath");
1671                                 return -rte_errno;
1672                         }
1673
1674                         spec_filter->template.efs_flags |=
1675                                 EFX_FILTER_FLAG_ACTION_FLAG;
1676                         break;
1677
1678                 case RTE_FLOW_ACTION_TYPE_MARK:
1679                         SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
1680                                                actions_set);
1681                         if ((actions_set & mark_actions_mask) != 0)
1682                                 goto fail_actions_overlap;
1683
1684                         if ((dp_rx_features & SFC_DP_RX_FEAT_FLOW_MARK) == 0) {
1685                                 rte_flow_error_set(error, ENOTSUP,
1686                                         RTE_FLOW_ERROR_TYPE_ACTION, NULL,
1687                                         "MARK action is not supported on the current Rx datapath");
1688                                 return -rte_errno;
1689                         }
1690
1691                         rc = sfc_flow_parse_mark(sa, actions->conf, flow);
1692                         if (rc != 0) {
1693                                 rte_flow_error_set(error, rc,
1694                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
1695                                         "Bad MARK action");
1696                                 return -rte_errno;
1697                         }
1698                         break;
1699
1700                 default:
1701                         rte_flow_error_set(error, ENOTSUP,
1702                                            RTE_FLOW_ERROR_TYPE_ACTION, actions,
1703                                            "Action is not supported");
1704                         return -rte_errno;
1705                 }
1706
1707                 actions_set |= (1UL << actions->type);
1708         }
1709 #undef SFC_BUILD_SET_OVERFLOW
1710
1711         /* When fate is unknown, drop traffic. */
1712         if ((actions_set & fate_actions_mask) == 0) {
1713                 spec_filter->template.efs_dmaq_id =
1714                         EFX_FILTER_SPEC_RX_DMAQ_ID_DROP;
1715         }
1716
1717         return 0;
1718
1719 fail_fate_actions:
1720         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions,
1721                            "Cannot combine several fate-deciding actions, "
1722                            "choose between QUEUE, RSS or DROP");
1723         return -rte_errno;
1724
1725 fail_actions_overlap:
1726         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, actions,
1727                            "Overlapping actions are not supported");
1728         return -rte_errno;
1729 }
1730
1731 /**
1732  * Set the EFX_FILTER_MATCH_UNKNOWN_UCAST_DST
1733  * and EFX_FILTER_MATCH_UNKNOWN_MCAST_DST match flags in the same
1734  * specifications after copying.
1735  *
1736  * @param spec[in, out]
1737  *   SFC flow specification to update.
1738  * @param filters_count_for_one_val[in]
1739  *   How many specifications should have the same match flag, what is the
1740  *   number of specifications before copying.
1741  * @param error[out]
1742  *   Perform verbose error reporting if not NULL.
1743  */
1744 static int
1745 sfc_flow_set_unknown_dst_flags(struct sfc_flow_spec *spec,
1746                                unsigned int filters_count_for_one_val,
1747                                struct rte_flow_error *error)
1748 {
1749         unsigned int i;
1750         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1751         static const efx_filter_match_flags_t vals[] = {
1752                 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST,
1753                 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST
1754         };
1755
1756         if (filters_count_for_one_val * RTE_DIM(vals) != spec_filter->count) {
1757                 rte_flow_error_set(error, EINVAL,
1758                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1759                         "Number of specifications is incorrect while copying "
1760                         "by unknown destination flags");
1761                 return -rte_errno;
1762         }
1763
1764         for (i = 0; i < spec_filter->count; i++) {
1765                 /* The check above ensures that divisor can't be zero here */
1766                 spec_filter->filters[i].efs_match_flags |=
1767                         vals[i / filters_count_for_one_val];
1768         }
1769
1770         return 0;
1771 }
1772
1773 /**
1774  * Check that the following conditions are met:
1775  * - the list of supported filters has a filter
1776  *   with EFX_FILTER_MATCH_UNKNOWN_MCAST_DST flag instead of
1777  *   EFX_FILTER_MATCH_UNKNOWN_UCAST_DST, since this filter will also
1778  *   be inserted.
1779  *
1780  * @param match[in]
1781  *   The match flags of filter.
1782  * @param spec[in]
1783  *   Specification to be supplemented.
1784  * @param filter[in]
1785  *   SFC filter with list of supported filters.
1786  */
1787 static boolean_t
1788 sfc_flow_check_unknown_dst_flags(efx_filter_match_flags_t match,
1789                                  __rte_unused efx_filter_spec_t *spec,
1790                                  struct sfc_filter *filter)
1791 {
1792         unsigned int i;
1793         efx_filter_match_flags_t match_mcast_dst;
1794
1795         match_mcast_dst =
1796                 (match & ~EFX_FILTER_MATCH_UNKNOWN_UCAST_DST) |
1797                 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
1798         for (i = 0; i < filter->supported_match_num; i++) {
1799                 if (match_mcast_dst == filter->supported_match[i])
1800                         return B_TRUE;
1801         }
1802
1803         return B_FALSE;
1804 }
1805
1806 /**
1807  * Set the EFX_FILTER_MATCH_ETHER_TYPE match flag and EFX_ETHER_TYPE_IPV4 and
1808  * EFX_ETHER_TYPE_IPV6 values of the corresponding field in the same
1809  * specifications after copying.
1810  *
1811  * @param spec[in, out]
1812  *   SFC flow specification to update.
1813  * @param filters_count_for_one_val[in]
1814  *   How many specifications should have the same EtherType value, what is the
1815  *   number of specifications before copying.
1816  * @param error[out]
1817  *   Perform verbose error reporting if not NULL.
1818  */
1819 static int
1820 sfc_flow_set_ethertypes(struct sfc_flow_spec *spec,
1821                         unsigned int filters_count_for_one_val,
1822                         struct rte_flow_error *error)
1823 {
1824         unsigned int i;
1825         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1826         static const uint16_t vals[] = {
1827                 EFX_ETHER_TYPE_IPV4, EFX_ETHER_TYPE_IPV6
1828         };
1829
1830         if (filters_count_for_one_val * RTE_DIM(vals) != spec_filter->count) {
1831                 rte_flow_error_set(error, EINVAL,
1832                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1833                         "Number of specifications is incorrect "
1834                         "while copying by Ethertype");
1835                 return -rte_errno;
1836         }
1837
1838         for (i = 0; i < spec_filter->count; i++) {
1839                 spec_filter->filters[i].efs_match_flags |=
1840                         EFX_FILTER_MATCH_ETHER_TYPE;
1841
1842                 /*
1843                  * The check above ensures that
1844                  * filters_count_for_one_val is not 0
1845                  */
1846                 spec_filter->filters[i].efs_ether_type =
1847                         vals[i / filters_count_for_one_val];
1848         }
1849
1850         return 0;
1851 }
1852
1853 /**
1854  * Set the EFX_FILTER_MATCH_OUTER_VID match flag with value 0
1855  * in the same specifications after copying.
1856  *
1857  * @param spec[in, out]
1858  *   SFC flow specification to update.
1859  * @param filters_count_for_one_val[in]
1860  *   How many specifications should have the same match flag, what is the
1861  *   number of specifications before copying.
1862  * @param error[out]
1863  *   Perform verbose error reporting if not NULL.
1864  */
1865 static int
1866 sfc_flow_set_outer_vid_flag(struct sfc_flow_spec *spec,
1867                             unsigned int filters_count_for_one_val,
1868                             struct rte_flow_error *error)
1869 {
1870         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1871         unsigned int i;
1872
1873         if (filters_count_for_one_val != spec_filter->count) {
1874                 rte_flow_error_set(error, EINVAL,
1875                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1876                         "Number of specifications is incorrect "
1877                         "while copying by outer VLAN ID");
1878                 return -rte_errno;
1879         }
1880
1881         for (i = 0; i < spec_filter->count; i++) {
1882                 spec_filter->filters[i].efs_match_flags |=
1883                         EFX_FILTER_MATCH_OUTER_VID;
1884
1885                 spec_filter->filters[i].efs_outer_vid = 0;
1886         }
1887
1888         return 0;
1889 }
1890
1891 /**
1892  * Set the EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST and
1893  * EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST match flags in the same
1894  * specifications after copying.
1895  *
1896  * @param spec[in, out]
1897  *   SFC flow specification to update.
1898  * @param filters_count_for_one_val[in]
1899  *   How many specifications should have the same match flag, what is the
1900  *   number of specifications before copying.
1901  * @param error[out]
1902  *   Perform verbose error reporting if not NULL.
1903  */
1904 static int
1905 sfc_flow_set_ifrm_unknown_dst_flags(struct sfc_flow_spec *spec,
1906                                     unsigned int filters_count_for_one_val,
1907                                     struct rte_flow_error *error)
1908 {
1909         unsigned int i;
1910         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
1911         static const efx_filter_match_flags_t vals[] = {
1912                 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST,
1913                 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST
1914         };
1915
1916         if (filters_count_for_one_val * RTE_DIM(vals) != spec_filter->count) {
1917                 rte_flow_error_set(error, EINVAL,
1918                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1919                         "Number of specifications is incorrect while copying "
1920                         "by inner frame unknown destination flags");
1921                 return -rte_errno;
1922         }
1923
1924         for (i = 0; i < spec_filter->count; i++) {
1925                 /* The check above ensures that divisor can't be zero here */
1926                 spec_filter->filters[i].efs_match_flags |=
1927                         vals[i / filters_count_for_one_val];
1928         }
1929
1930         return 0;
1931 }
1932
1933 /**
1934  * Check that the following conditions are met:
1935  * - the specification corresponds to a filter for encapsulated traffic
1936  * - the list of supported filters has a filter
1937  *   with EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST flag instead of
1938  *   EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST, since this filter will also
1939  *   be inserted.
1940  *
1941  * @param match[in]
1942  *   The match flags of filter.
1943  * @param spec[in]
1944  *   Specification to be supplemented.
1945  * @param filter[in]
1946  *   SFC filter with list of supported filters.
1947  */
1948 static boolean_t
1949 sfc_flow_check_ifrm_unknown_dst_flags(efx_filter_match_flags_t match,
1950                                       efx_filter_spec_t *spec,
1951                                       struct sfc_filter *filter)
1952 {
1953         unsigned int i;
1954         efx_tunnel_protocol_t encap_type = spec->efs_encap_type;
1955         efx_filter_match_flags_t match_mcast_dst;
1956
1957         if (encap_type == EFX_TUNNEL_PROTOCOL_NONE)
1958                 return B_FALSE;
1959
1960         match_mcast_dst =
1961                 (match & ~EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST) |
1962                 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST;
1963         for (i = 0; i < filter->supported_match_num; i++) {
1964                 if (match_mcast_dst == filter->supported_match[i])
1965                         return B_TRUE;
1966         }
1967
1968         return B_FALSE;
1969 }
1970
1971 /**
1972  * Check that the list of supported filters has a filter that differs
1973  * from @p match in that it has no flag EFX_FILTER_MATCH_OUTER_VID
1974  * in this case that filter will be used and the flag
1975  * EFX_FILTER_MATCH_OUTER_VID is not needed.
1976  *
1977  * @param match[in]
1978  *   The match flags of filter.
1979  * @param spec[in]
1980  *   Specification to be supplemented.
1981  * @param filter[in]
1982  *   SFC filter with list of supported filters.
1983  */
1984 static boolean_t
1985 sfc_flow_check_outer_vid_flag(efx_filter_match_flags_t match,
1986                               __rte_unused efx_filter_spec_t *spec,
1987                               struct sfc_filter *filter)
1988 {
1989         unsigned int i;
1990         efx_filter_match_flags_t match_without_vid =
1991                 match & ~EFX_FILTER_MATCH_OUTER_VID;
1992
1993         for (i = 0; i < filter->supported_match_num; i++) {
1994                 if (match_without_vid == filter->supported_match[i])
1995                         return B_FALSE;
1996         }
1997
1998         return B_TRUE;
1999 }
2000
2001 /*
2002  * Match flags that can be automatically added to filters.
2003  * Selecting the last minimum when searching for the copy flag ensures that the
2004  * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST flag has a higher priority than
2005  * EFX_FILTER_MATCH_ETHER_TYPE. This is because the filter
2006  * EFX_FILTER_MATCH_UNKNOWN_UCAST_DST is at the end of the list of supported
2007  * filters.
2008  */
2009 static const struct sfc_flow_copy_flag sfc_flow_copy_flags[] = {
2010         {
2011                 .flag = EFX_FILTER_MATCH_UNKNOWN_UCAST_DST,
2012                 .vals_count = 2,
2013                 .set_vals = sfc_flow_set_unknown_dst_flags,
2014                 .spec_check = sfc_flow_check_unknown_dst_flags,
2015         },
2016         {
2017                 .flag = EFX_FILTER_MATCH_ETHER_TYPE,
2018                 .vals_count = 2,
2019                 .set_vals = sfc_flow_set_ethertypes,
2020                 .spec_check = NULL,
2021         },
2022         {
2023                 .flag = EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST,
2024                 .vals_count = 2,
2025                 .set_vals = sfc_flow_set_ifrm_unknown_dst_flags,
2026                 .spec_check = sfc_flow_check_ifrm_unknown_dst_flags,
2027         },
2028         {
2029                 .flag = EFX_FILTER_MATCH_OUTER_VID,
2030                 .vals_count = 1,
2031                 .set_vals = sfc_flow_set_outer_vid_flag,
2032                 .spec_check = sfc_flow_check_outer_vid_flag,
2033         },
2034 };
2035
2036 /* Get item from array sfc_flow_copy_flags */
2037 static const struct sfc_flow_copy_flag *
2038 sfc_flow_get_copy_flag(efx_filter_match_flags_t flag)
2039 {
2040         unsigned int i;
2041
2042         for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
2043                 if (sfc_flow_copy_flags[i].flag == flag)
2044                         return &sfc_flow_copy_flags[i];
2045         }
2046
2047         return NULL;
2048 }
2049
2050 /**
2051  * Make copies of the specifications, set match flag and values
2052  * of the field that corresponds to it.
2053  *
2054  * @param spec[in, out]
2055  *   SFC flow specification to update.
2056  * @param flag[in]
2057  *   The match flag to add.
2058  * @param error[out]
2059  *   Perform verbose error reporting if not NULL.
2060  */
2061 static int
2062 sfc_flow_spec_add_match_flag(struct sfc_flow_spec *spec,
2063                              efx_filter_match_flags_t flag,
2064                              struct rte_flow_error *error)
2065 {
2066         unsigned int i;
2067         unsigned int new_filters_count;
2068         unsigned int filters_count_for_one_val;
2069         const struct sfc_flow_copy_flag *copy_flag;
2070         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
2071         int rc;
2072
2073         copy_flag = sfc_flow_get_copy_flag(flag);
2074         if (copy_flag == NULL) {
2075                 rte_flow_error_set(error, ENOTSUP,
2076                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2077                                    "Unsupported spec field for copying");
2078                 return -rte_errno;
2079         }
2080
2081         new_filters_count = spec_filter->count * copy_flag->vals_count;
2082         if (new_filters_count > SF_FLOW_SPEC_NB_FILTERS_MAX) {
2083                 rte_flow_error_set(error, EINVAL,
2084                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2085                         "Too much EFX specifications in the flow rule");
2086                 return -rte_errno;
2087         }
2088
2089         /* Copy filters specifications */
2090         for (i = spec_filter->count; i < new_filters_count; i++) {
2091                 spec_filter->filters[i] =
2092                         spec_filter->filters[i - spec_filter->count];
2093         }
2094
2095         filters_count_for_one_val = spec_filter->count;
2096         spec_filter->count = new_filters_count;
2097
2098         rc = copy_flag->set_vals(spec, filters_count_for_one_val, error);
2099         if (rc != 0)
2100                 return rc;
2101
2102         return 0;
2103 }
2104
2105 /**
2106  * Check that the given set of match flags missing in the original filter spec
2107  * could be covered by adding spec copies which specify the corresponding
2108  * flags and packet field values to match.
2109  *
2110  * @param miss_flags[in]
2111  *   Flags that are missing until the supported filter.
2112  * @param spec[in]
2113  *   Specification to be supplemented.
2114  * @param filter[in]
2115  *   SFC filter.
2116  *
2117  * @return
2118  *   Number of specifications after copy or 0, if the flags can not be added.
2119  */
2120 static unsigned int
2121 sfc_flow_check_missing_flags(efx_filter_match_flags_t miss_flags,
2122                              efx_filter_spec_t *spec,
2123                              struct sfc_filter *filter)
2124 {
2125         unsigned int i;
2126         efx_filter_match_flags_t copy_flags = 0;
2127         efx_filter_match_flags_t flag;
2128         efx_filter_match_flags_t match = spec->efs_match_flags | miss_flags;
2129         sfc_flow_spec_check *check;
2130         unsigned int multiplier = 1;
2131
2132         for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
2133                 flag = sfc_flow_copy_flags[i].flag;
2134                 check = sfc_flow_copy_flags[i].spec_check;
2135                 if ((flag & miss_flags) == flag) {
2136                         if (check != NULL && (!check(match, spec, filter)))
2137                                 continue;
2138
2139                         copy_flags |= flag;
2140                         multiplier *= sfc_flow_copy_flags[i].vals_count;
2141                 }
2142         }
2143
2144         if (copy_flags == miss_flags)
2145                 return multiplier;
2146
2147         return 0;
2148 }
2149
2150 /**
2151  * Attempt to supplement the specification template to the minimally
2152  * supported set of match flags. To do this, it is necessary to copy
2153  * the specifications, filling them with the values of fields that
2154  * correspond to the missing flags.
2155  * The necessary and sufficient filter is built from the fewest number
2156  * of copies which could be made to cover the minimally required set
2157  * of flags.
2158  *
2159  * @param sa[in]
2160  *   SFC adapter.
2161  * @param spec[in, out]
2162  *   SFC flow specification to update.
2163  * @param error[out]
2164  *   Perform verbose error reporting if not NULL.
2165  */
2166 static int
2167 sfc_flow_spec_filters_complete(struct sfc_adapter *sa,
2168                                struct sfc_flow_spec *spec,
2169                                struct rte_flow_error *error)
2170 {
2171         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
2172         struct sfc_filter *filter = &sa->filter;
2173         efx_filter_match_flags_t miss_flags;
2174         efx_filter_match_flags_t min_miss_flags = 0;
2175         efx_filter_match_flags_t match;
2176         unsigned int min_multiplier = UINT_MAX;
2177         unsigned int multiplier;
2178         unsigned int i;
2179         int rc;
2180
2181         match = spec_filter->template.efs_match_flags;
2182         for (i = 0; i < filter->supported_match_num; i++) {
2183                 if ((match & filter->supported_match[i]) == match) {
2184                         miss_flags = filter->supported_match[i] & (~match);
2185                         multiplier = sfc_flow_check_missing_flags(miss_flags,
2186                                 &spec_filter->template, filter);
2187                         if (multiplier > 0) {
2188                                 if (multiplier <= min_multiplier) {
2189                                         min_multiplier = multiplier;
2190                                         min_miss_flags = miss_flags;
2191                                 }
2192                         }
2193                 }
2194         }
2195
2196         if (min_multiplier == UINT_MAX) {
2197                 rte_flow_error_set(error, ENOTSUP,
2198                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2199                                    "The flow rule pattern is unsupported");
2200                 return -rte_errno;
2201         }
2202
2203         for (i = 0; i < RTE_DIM(sfc_flow_copy_flags); i++) {
2204                 efx_filter_match_flags_t flag = sfc_flow_copy_flags[i].flag;
2205
2206                 if ((flag & min_miss_flags) == flag) {
2207                         rc = sfc_flow_spec_add_match_flag(spec, flag, error);
2208                         if (rc != 0)
2209                                 return rc;
2210                 }
2211         }
2212
2213         return 0;
2214 }
2215
2216 /**
2217  * Check that set of match flags is referred to by a filter. Filter is
2218  * described by match flags with the ability to add OUTER_VID and INNER_VID
2219  * flags.
2220  *
2221  * @param match_flags[in]
2222  *   Set of match flags.
2223  * @param flags_pattern[in]
2224  *   Pattern of filter match flags.
2225  */
2226 static boolean_t
2227 sfc_flow_is_match_with_vids(efx_filter_match_flags_t match_flags,
2228                             efx_filter_match_flags_t flags_pattern)
2229 {
2230         if ((match_flags & flags_pattern) != flags_pattern)
2231                 return B_FALSE;
2232
2233         switch (match_flags & ~flags_pattern) {
2234         case 0:
2235         case EFX_FILTER_MATCH_OUTER_VID:
2236         case EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_INNER_VID:
2237                 return B_TRUE;
2238         default:
2239                 return B_FALSE;
2240         }
2241 }
2242
2243 /**
2244  * Check whether the spec maps to a hardware filter which is known to be
2245  * ineffective despite being valid.
2246  *
2247  * @param filter[in]
2248  *   SFC filter with list of supported filters.
2249  * @param spec[in]
2250  *   SFC flow specification.
2251  */
2252 static boolean_t
2253 sfc_flow_is_match_flags_exception(struct sfc_filter *filter,
2254                                   struct sfc_flow_spec *spec)
2255 {
2256         unsigned int i;
2257         uint16_t ether_type;
2258         uint8_t ip_proto;
2259         efx_filter_match_flags_t match_flags;
2260         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
2261
2262         for (i = 0; i < spec_filter->count; i++) {
2263                 match_flags = spec_filter->filters[i].efs_match_flags;
2264
2265                 if (sfc_flow_is_match_with_vids(match_flags,
2266                                                 EFX_FILTER_MATCH_ETHER_TYPE) ||
2267                     sfc_flow_is_match_with_vids(match_flags,
2268                                                 EFX_FILTER_MATCH_ETHER_TYPE |
2269                                                 EFX_FILTER_MATCH_LOC_MAC)) {
2270                         ether_type = spec_filter->filters[i].efs_ether_type;
2271                         if (filter->supports_ip_proto_or_addr_filter &&
2272                             (ether_type == EFX_ETHER_TYPE_IPV4 ||
2273                              ether_type == EFX_ETHER_TYPE_IPV6))
2274                                 return B_TRUE;
2275                 } else if (sfc_flow_is_match_with_vids(match_flags,
2276                                 EFX_FILTER_MATCH_ETHER_TYPE |
2277                                 EFX_FILTER_MATCH_IP_PROTO) ||
2278                            sfc_flow_is_match_with_vids(match_flags,
2279                                 EFX_FILTER_MATCH_ETHER_TYPE |
2280                                 EFX_FILTER_MATCH_IP_PROTO |
2281                                 EFX_FILTER_MATCH_LOC_MAC)) {
2282                         ip_proto = spec_filter->filters[i].efs_ip_proto;
2283                         if (filter->supports_rem_or_local_port_filter &&
2284                             (ip_proto == EFX_IPPROTO_TCP ||
2285                              ip_proto == EFX_IPPROTO_UDP))
2286                                 return B_TRUE;
2287                 }
2288         }
2289
2290         return B_FALSE;
2291 }
2292
2293 static int
2294 sfc_flow_validate_match_flags(struct sfc_adapter *sa,
2295                               struct rte_flow *flow,
2296                               struct rte_flow_error *error)
2297 {
2298         struct sfc_flow_spec *spec = &flow->spec;
2299         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
2300         efx_filter_spec_t *spec_tmpl = &spec_filter->template;
2301         efx_filter_match_flags_t match_flags = spec_tmpl->efs_match_flags;
2302         int rc;
2303
2304         /* Initialize the first filter spec with template */
2305         spec_filter->filters[0] = *spec_tmpl;
2306         spec_filter->count = 1;
2307
2308         if (!sfc_filter_is_match_supported(sa, match_flags)) {
2309                 rc = sfc_flow_spec_filters_complete(sa, &flow->spec, error);
2310                 if (rc != 0)
2311                         return rc;
2312         }
2313
2314         if (sfc_flow_is_match_flags_exception(&sa->filter, &flow->spec)) {
2315                 rte_flow_error_set(error, ENOTSUP,
2316                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2317                         "The flow rule pattern is unsupported");
2318                 return -rte_errno;
2319         }
2320
2321         return 0;
2322 }
2323
2324 static int
2325 sfc_flow_parse_rte_to_filter(struct rte_eth_dev *dev,
2326                              const struct rte_flow_item pattern[],
2327                              const struct rte_flow_action actions[],
2328                              struct rte_flow *flow,
2329                              struct rte_flow_error *error)
2330 {
2331         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
2332         struct sfc_flow_spec *spec = &flow->spec;
2333         struct sfc_flow_spec_filter *spec_filter = &spec->filter;
2334         struct sfc_flow_parse_ctx ctx;
2335         int rc;
2336
2337         ctx.type = SFC_FLOW_PARSE_CTX_FILTER;
2338         ctx.filter = &spec_filter->template;
2339
2340         rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items),
2341                                     pattern, &ctx, error);
2342         if (rc != 0)
2343                 goto fail_bad_value;
2344
2345         rc = sfc_flow_parse_actions(sa, actions, flow, error);
2346         if (rc != 0)
2347                 goto fail_bad_value;
2348
2349         rc = sfc_flow_validate_match_flags(sa, flow, error);
2350         if (rc != 0)
2351                 goto fail_bad_value;
2352
2353         return 0;
2354
2355 fail_bad_value:
2356         return rc;
2357 }
2358
2359 static int
2360 sfc_flow_parse(struct rte_eth_dev *dev,
2361                const struct rte_flow_attr *attr,
2362                const struct rte_flow_item pattern[],
2363                const struct rte_flow_action actions[],
2364                struct rte_flow *flow,
2365                struct rte_flow_error *error)
2366 {
2367         const struct sfc_flow_ops_by_spec *ops;
2368         int rc;
2369
2370         rc = sfc_flow_parse_attr(attr, flow, error);
2371         if (rc != 0)
2372                 return rc;
2373
2374         ops = sfc_flow_get_ops_by_spec(flow);
2375         if (ops == NULL || ops->parse == NULL) {
2376                 rte_flow_error_set(error, ENOTSUP,
2377                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2378                                    "No backend to handle this flow");
2379                 return -rte_errno;
2380         }
2381
2382         return ops->parse(dev, pattern, actions, flow, error);
2383 }
2384
2385 static struct rte_flow *
2386 sfc_flow_zmalloc(struct rte_flow_error *error)
2387 {
2388         struct rte_flow *flow;
2389
2390         flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0);
2391         if (flow == NULL) {
2392                 rte_flow_error_set(error, ENOMEM,
2393                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2394                                    "Failed to allocate memory");
2395         }
2396
2397         return flow;
2398 }
2399
2400 static void
2401 sfc_flow_free(__rte_unused struct sfc_adapter *sa, struct rte_flow *flow)
2402 {
2403         rte_free(flow);
2404 }
2405
2406 static int
2407 sfc_flow_insert(struct sfc_adapter *sa, struct rte_flow *flow,
2408                 struct rte_flow_error *error)
2409 {
2410         const struct sfc_flow_ops_by_spec *ops;
2411         int rc;
2412
2413         ops = sfc_flow_get_ops_by_spec(flow);
2414         if (ops == NULL || ops->insert == NULL) {
2415                 rte_flow_error_set(error, ENOTSUP,
2416                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2417                                    "No backend to handle this flow");
2418                 return rte_errno;
2419         }
2420
2421         rc = ops->insert(sa, flow);
2422         if (rc != 0) {
2423                 rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2424                                    NULL, "Failed to insert the flow rule");
2425         }
2426
2427         return rc;
2428 }
2429
2430 static int
2431 sfc_flow_remove(struct sfc_adapter *sa, struct rte_flow *flow,
2432                 struct rte_flow_error *error)
2433 {
2434         const struct sfc_flow_ops_by_spec *ops;
2435         int rc;
2436
2437         ops = sfc_flow_get_ops_by_spec(flow);
2438         if (ops == NULL || ops->remove == NULL) {
2439                 rte_flow_error_set(error, ENOTSUP,
2440                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2441                                    "No backend to handle this flow");
2442                 return rte_errno;
2443         }
2444
2445         rc = ops->remove(sa, flow);
2446         if (rc != 0) {
2447                 rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2448                                    NULL, "Failed to remove the flow rule");
2449         }
2450
2451         return rc;
2452 }
2453
2454 static int
2455 sfc_flow_validate(struct rte_eth_dev *dev,
2456                   const struct rte_flow_attr *attr,
2457                   const struct rte_flow_item pattern[],
2458                   const struct rte_flow_action actions[],
2459                   struct rte_flow_error *error)
2460 {
2461         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
2462         struct rte_flow *flow;
2463         int rc;
2464
2465         flow = sfc_flow_zmalloc(error);
2466         if (flow == NULL)
2467                 return -rte_errno;
2468
2469         rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
2470
2471         sfc_flow_free(sa, flow);
2472
2473         return rc;
2474 }
2475
2476 static struct rte_flow *
2477 sfc_flow_create(struct rte_eth_dev *dev,
2478                 const struct rte_flow_attr *attr,
2479                 const struct rte_flow_item pattern[],
2480                 const struct rte_flow_action actions[],
2481                 struct rte_flow_error *error)
2482 {
2483         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
2484         struct rte_flow *flow = NULL;
2485         int rc;
2486
2487         flow = sfc_flow_zmalloc(error);
2488         if (flow == NULL)
2489                 goto fail_no_mem;
2490
2491         rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
2492         if (rc != 0)
2493                 goto fail_bad_value;
2494
2495         sfc_adapter_lock(sa);
2496
2497         TAILQ_INSERT_TAIL(&sa->flow_list, flow, entries);
2498
2499         if (sa->state == SFC_ADAPTER_STARTED) {
2500                 rc = sfc_flow_insert(sa, flow, error);
2501                 if (rc != 0)
2502                         goto fail_flow_insert;
2503         }
2504
2505         sfc_adapter_unlock(sa);
2506
2507         return flow;
2508
2509 fail_flow_insert:
2510         TAILQ_REMOVE(&sa->flow_list, flow, entries);
2511
2512 fail_bad_value:
2513         sfc_flow_free(sa, flow);
2514         sfc_adapter_unlock(sa);
2515
2516 fail_no_mem:
2517         return NULL;
2518 }
2519
2520 static int
2521 sfc_flow_destroy(struct rte_eth_dev *dev,
2522                  struct rte_flow *flow,
2523                  struct rte_flow_error *error)
2524 {
2525         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
2526         struct rte_flow *flow_ptr;
2527         int rc = EINVAL;
2528
2529         sfc_adapter_lock(sa);
2530
2531         TAILQ_FOREACH(flow_ptr, &sa->flow_list, entries) {
2532                 if (flow_ptr == flow)
2533                         rc = 0;
2534         }
2535         if (rc != 0) {
2536                 rte_flow_error_set(error, rc,
2537                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
2538                                    "Failed to find flow rule to destroy");
2539                 goto fail_bad_value;
2540         }
2541
2542         if (sa->state == SFC_ADAPTER_STARTED)
2543                 rc = sfc_flow_remove(sa, flow, error);
2544
2545         TAILQ_REMOVE(&sa->flow_list, flow, entries);
2546         sfc_flow_free(sa, flow);
2547
2548 fail_bad_value:
2549         sfc_adapter_unlock(sa);
2550
2551         return -rc;
2552 }
2553
2554 static int
2555 sfc_flow_flush(struct rte_eth_dev *dev,
2556                struct rte_flow_error *error)
2557 {
2558         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
2559         struct rte_flow *flow;
2560         int ret = 0;
2561
2562         sfc_adapter_lock(sa);
2563
2564         while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
2565                 if (sa->state == SFC_ADAPTER_STARTED) {
2566                         int rc;
2567
2568                         rc = sfc_flow_remove(sa, flow, error);
2569                         if (rc != 0)
2570                                 ret = rc;
2571                 }
2572
2573                 TAILQ_REMOVE(&sa->flow_list, flow, entries);
2574                 sfc_flow_free(sa, flow);
2575         }
2576
2577         sfc_adapter_unlock(sa);
2578
2579         return -ret;
2580 }
2581
2582 static int
2583 sfc_flow_isolate(struct rte_eth_dev *dev, int enable,
2584                  struct rte_flow_error *error)
2585 {
2586         struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
2587         int ret = 0;
2588
2589         sfc_adapter_lock(sa);
2590         if (sa->state != SFC_ADAPTER_INITIALIZED) {
2591                 rte_flow_error_set(error, EBUSY,
2592                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2593                                    NULL, "please close the port first");
2594                 ret = -rte_errno;
2595         } else {
2596                 sfc_sa2shared(sa)->isolated = (enable) ? B_TRUE : B_FALSE;
2597         }
2598         sfc_adapter_unlock(sa);
2599
2600         return ret;
2601 }
2602
2603 const struct rte_flow_ops sfc_flow_ops = {
2604         .validate = sfc_flow_validate,
2605         .create = sfc_flow_create,
2606         .destroy = sfc_flow_destroy,
2607         .flush = sfc_flow_flush,
2608         .query = NULL,
2609         .isolate = sfc_flow_isolate,
2610 };
2611
2612 void
2613 sfc_flow_init(struct sfc_adapter *sa)
2614 {
2615         SFC_ASSERT(sfc_adapter_is_locked(sa));
2616
2617         TAILQ_INIT(&sa->flow_list);
2618 }
2619
2620 void
2621 sfc_flow_fini(struct sfc_adapter *sa)
2622 {
2623         struct rte_flow *flow;
2624
2625         SFC_ASSERT(sfc_adapter_is_locked(sa));
2626
2627         while ((flow = TAILQ_FIRST(&sa->flow_list)) != NULL) {
2628                 TAILQ_REMOVE(&sa->flow_list, flow, entries);
2629                 sfc_flow_free(sa, flow);
2630         }
2631 }
2632
2633 void
2634 sfc_flow_stop(struct sfc_adapter *sa)
2635 {
2636         struct rte_flow *flow;
2637
2638         SFC_ASSERT(sfc_adapter_is_locked(sa));
2639
2640         TAILQ_FOREACH(flow, &sa->flow_list, entries)
2641                 sfc_flow_remove(sa, flow, NULL);
2642 }
2643
2644 int
2645 sfc_flow_start(struct sfc_adapter *sa)
2646 {
2647         struct rte_flow *flow;
2648         int rc = 0;
2649
2650         sfc_log_init(sa, "entry");
2651
2652         SFC_ASSERT(sfc_adapter_is_locked(sa));
2653
2654         TAILQ_FOREACH(flow, &sa->flow_list, entries) {
2655                 rc = sfc_flow_insert(sa, flow, NULL);
2656                 if (rc != 0)
2657                         goto fail_bad_flow;
2658         }
2659
2660         sfc_log_init(sa, "done");
2661
2662 fail_bad_flow:
2663         return rc;
2664 }