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