New upstream version 17.11.4
[deb_dpdk.git] / drivers / net / sfc / sfc_flow.c
1 /*-
2  *   BSD LICENSE
3  *
4  * Copyright (c) 2017 Solarflare Communications Inc.
5  * All rights reserved.
6  *
7  * This software was jointly developed between OKTET Labs (under contract
8  * for Solarflare) and Solarflare Communications, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright notice,
14  *    this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  *    this list of conditions and the following disclaimer in the documentation
17  *    and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <rte_tailq.h>
33 #include <rte_common.h>
34 #include <rte_ethdev.h>
35 #include <rte_eth_ctrl.h>
36 #include <rte_ether.h>
37 #include <rte_flow.h>
38 #include <rte_flow_driver.h>
39
40 #include "efx.h"
41
42 #include "sfc.h"
43 #include "sfc_rx.h"
44 #include "sfc_filter.h"
45 #include "sfc_flow.h"
46 #include "sfc_log.h"
47
48 /*
49  * At now flow API is implemented in such a manner that each
50  * flow rule is converted to a hardware filter.
51  * All elements of flow rule (attributes, pattern items, actions)
52  * correspond to one or more fields in the efx_filter_spec_s structure
53  * that is responsible for the hardware filter.
54  */
55
56 enum sfc_flow_item_layers {
57         SFC_FLOW_ITEM_ANY_LAYER,
58         SFC_FLOW_ITEM_START_LAYER,
59         SFC_FLOW_ITEM_L2,
60         SFC_FLOW_ITEM_L3,
61         SFC_FLOW_ITEM_L4,
62 };
63
64 typedef int (sfc_flow_item_parse)(const struct rte_flow_item *item,
65                                   efx_filter_spec_t *spec,
66                                   struct rte_flow_error *error);
67
68 struct sfc_flow_item {
69         enum rte_flow_item_type type;           /* Type of item */
70         enum sfc_flow_item_layers layer;        /* Layer of item */
71         enum sfc_flow_item_layers prev_layer;   /* Previous layer of item */
72         sfc_flow_item_parse *parse;             /* Parsing function */
73 };
74
75 static sfc_flow_item_parse sfc_flow_parse_void;
76 static sfc_flow_item_parse sfc_flow_parse_eth;
77 static sfc_flow_item_parse sfc_flow_parse_vlan;
78 static sfc_flow_item_parse sfc_flow_parse_ipv4;
79 static sfc_flow_item_parse sfc_flow_parse_ipv6;
80 static sfc_flow_item_parse sfc_flow_parse_tcp;
81 static sfc_flow_item_parse sfc_flow_parse_udp;
82
83 static boolean_t
84 sfc_flow_is_zero(const uint8_t *buf, unsigned int size)
85 {
86         uint8_t sum = 0;
87         unsigned int i;
88
89         for (i = 0; i < size; i++)
90                 sum |= buf[i];
91
92         return (sum == 0) ? B_TRUE : B_FALSE;
93 }
94
95 /*
96  * Validate item and prepare structures spec and mask for parsing
97  */
98 static int
99 sfc_flow_parse_init(const struct rte_flow_item *item,
100                     const void **spec_ptr,
101                     const void **mask_ptr,
102                     const void *supp_mask,
103                     const void *def_mask,
104                     unsigned int size,
105                     struct rte_flow_error *error)
106 {
107         const uint8_t *spec;
108         const uint8_t *mask;
109         const uint8_t *last;
110         uint8_t supp;
111         unsigned int i;
112
113         if (item == NULL) {
114                 rte_flow_error_set(error, EINVAL,
115                                    RTE_FLOW_ERROR_TYPE_ITEM, NULL,
116                                    "NULL item");
117                 return -rte_errno;
118         }
119
120         if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) {
121                 rte_flow_error_set(error, EINVAL,
122                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
123                                    "Mask or last is set without spec");
124                 return -rte_errno;
125         }
126
127         /*
128          * If "mask" is not set, default mask is used,
129          * but if default mask is NULL, "mask" should be set
130          */
131         if (item->mask == NULL) {
132                 if (def_mask == NULL) {
133                         rte_flow_error_set(error, EINVAL,
134                                 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
135                                 "Mask should be specified");
136                         return -rte_errno;
137                 }
138
139                 mask = (const uint8_t *)def_mask;
140         } else {
141                 mask = (const uint8_t *)item->mask;
142         }
143
144         spec = (const uint8_t *)item->spec;
145         last = (const uint8_t *)item->last;
146
147         if (spec == NULL)
148                 goto exit;
149
150         /*
151          * If field values in "last" are either 0 or equal to the corresponding
152          * values in "spec" then they are ignored
153          */
154         if (last != NULL &&
155             !sfc_flow_is_zero(last, size) &&
156             memcmp(last, spec, size) != 0) {
157                 rte_flow_error_set(error, ENOTSUP,
158                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
159                                    "Ranging is not supported");
160                 return -rte_errno;
161         }
162
163         if (supp_mask == NULL) {
164                 rte_flow_error_set(error, EINVAL,
165                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
166                         "Supported mask for item should be specified");
167                 return -rte_errno;
168         }
169
170         /* Check that mask does not ask for more match than supp_mask */
171         for (i = 0; i < size; i++) {
172                 supp = ((const uint8_t *)supp_mask)[i];
173
174                 if (~supp & mask[i]) {
175                         rte_flow_error_set(error, ENOTSUP,
176                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
177                                            "Item's field is not supported");
178                         return -rte_errno;
179                 }
180         }
181
182 exit:
183         *spec_ptr = spec;
184         *mask_ptr = mask;
185         return 0;
186 }
187
188 /*
189  * Protocol parsers.
190  * Masking is not supported, so masks in items should be either
191  * full or empty (zeroed) and set only for supported fields which
192  * are specified in the supp_mask.
193  */
194
195 static int
196 sfc_flow_parse_void(__rte_unused const struct rte_flow_item *item,
197                     __rte_unused efx_filter_spec_t *efx_spec,
198                     __rte_unused struct rte_flow_error *error)
199 {
200         return 0;
201 }
202
203 /**
204  * Convert Ethernet item to EFX filter specification.
205  *
206  * @param item[in]
207  *   Item specification. Only source and destination addresses and
208  *   Ethernet type fields are supported. In addition to full and
209  *   empty masks of destination address, individual/group mask is
210  *   also supported. If the mask is NULL, default mask will be used.
211  *   Ranging is not supported.
212  * @param efx_spec[in, out]
213  *   EFX filter specification to update.
214  * @param[out] error
215  *   Perform verbose error reporting if not NULL.
216  */
217 static int
218 sfc_flow_parse_eth(const struct rte_flow_item *item,
219                    efx_filter_spec_t *efx_spec,
220                    struct rte_flow_error *error)
221 {
222         int rc;
223         const struct rte_flow_item_eth *spec = NULL;
224         const struct rte_flow_item_eth *mask = NULL;
225         const struct rte_flow_item_eth supp_mask = {
226                 .dst.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
227                 .src.addr_bytes = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
228                 .type = 0xffff,
229         };
230         const uint8_t ig_mask[EFX_MAC_ADDR_LEN] = {
231                 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
232         };
233
234         rc = sfc_flow_parse_init(item,
235                                  (const void **)&spec,
236                                  (const void **)&mask,
237                                  &supp_mask,
238                                  &rte_flow_item_eth_mask,
239                                  sizeof(struct rte_flow_item_eth),
240                                  error);
241         if (rc != 0)
242                 return rc;
243
244         /* If "spec" is not set, could be any Ethernet */
245         if (spec == NULL)
246                 return 0;
247
248         if (is_same_ether_addr(&mask->dst, &supp_mask.dst)) {
249                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_MAC;
250                 rte_memcpy(efx_spec->efs_loc_mac, spec->dst.addr_bytes,
251                            EFX_MAC_ADDR_LEN);
252         } else if (memcmp(mask->dst.addr_bytes, ig_mask,
253                           EFX_MAC_ADDR_LEN) == 0) {
254                 if (is_unicast_ether_addr(&spec->dst))
255                         efx_spec->efs_match_flags |=
256                                 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST;
257                 else
258                         efx_spec->efs_match_flags |=
259                                 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST;
260         } else if (!is_zero_ether_addr(&mask->dst)) {
261                 goto fail_bad_mask;
262         }
263
264         if (is_same_ether_addr(&mask->src, &supp_mask.src)) {
265                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_MAC;
266                 rte_memcpy(efx_spec->efs_rem_mac, spec->src.addr_bytes,
267                            EFX_MAC_ADDR_LEN);
268         } else if (!is_zero_ether_addr(&mask->src)) {
269                 goto fail_bad_mask;
270         }
271
272         /*
273          * Ether type is in big-endian byte order in item and
274          * in little-endian in efx_spec, so byte swap is used
275          */
276         if (mask->type == supp_mask.type) {
277                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
278                 efx_spec->efs_ether_type = rte_bswap16(spec->type);
279         } else if (mask->type != 0) {
280                 goto fail_bad_mask;
281         }
282
283         return 0;
284
285 fail_bad_mask:
286         rte_flow_error_set(error, EINVAL,
287                            RTE_FLOW_ERROR_TYPE_ITEM, item,
288                            "Bad mask in the ETH pattern item");
289         return -rte_errno;
290 }
291
292 /**
293  * Convert VLAN item to EFX filter specification.
294  *
295  * @param item[in]
296  *   Item specification. Only VID field is supported.
297  *   The mask can not be NULL. Ranging is not supported.
298  * @param efx_spec[in, out]
299  *   EFX filter specification to update.
300  * @param[out] error
301  *   Perform verbose error reporting if not NULL.
302  */
303 static int
304 sfc_flow_parse_vlan(const struct rte_flow_item *item,
305                     efx_filter_spec_t *efx_spec,
306                     struct rte_flow_error *error)
307 {
308         int rc;
309         uint16_t vid;
310         const struct rte_flow_item_vlan *spec = NULL;
311         const struct rte_flow_item_vlan *mask = NULL;
312         const struct rte_flow_item_vlan supp_mask = {
313                 .tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX),
314         };
315
316         rc = sfc_flow_parse_init(item,
317                                  (const void **)&spec,
318                                  (const void **)&mask,
319                                  &supp_mask,
320                                  NULL,
321                                  sizeof(struct rte_flow_item_vlan),
322                                  error);
323         if (rc != 0)
324                 return rc;
325
326         /*
327          * VID is in big-endian byte order in item and
328          * in little-endian in efx_spec, so byte swap is used.
329          * If two VLAN items are included, the first matches
330          * the outer tag and the next matches the inner tag.
331          */
332         if (mask->tci == supp_mask.tci) {
333                 /* Apply mask to keep VID only */
334                 vid = rte_bswap16(spec->tci & mask->tci);
335
336                 if (!(efx_spec->efs_match_flags &
337                       EFX_FILTER_MATCH_OUTER_VID)) {
338                         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
339                         efx_spec->efs_outer_vid = vid;
340                 } else if (!(efx_spec->efs_match_flags &
341                              EFX_FILTER_MATCH_INNER_VID)) {
342                         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID;
343                         efx_spec->efs_inner_vid = vid;
344                 } else {
345                         rte_flow_error_set(error, EINVAL,
346                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
347                                            "More than two VLAN items");
348                         return -rte_errno;
349                 }
350         } else {
351                 rte_flow_error_set(error, EINVAL,
352                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
353                                    "VLAN ID in TCI match is required");
354                 return -rte_errno;
355         }
356
357         return 0;
358 }
359
360 /**
361  * Convert IPv4 item to EFX filter specification.
362  *
363  * @param item[in]
364  *   Item specification. Only source and destination addresses and
365  *   protocol fields are supported. If the mask is NULL, default
366  *   mask will be used. Ranging is not supported.
367  * @param efx_spec[in, out]
368  *   EFX filter specification to update.
369  * @param[out] error
370  *   Perform verbose error reporting if not NULL.
371  */
372 static int
373 sfc_flow_parse_ipv4(const struct rte_flow_item *item,
374                     efx_filter_spec_t *efx_spec,
375                     struct rte_flow_error *error)
376 {
377         int rc;
378         const struct rte_flow_item_ipv4 *spec = NULL;
379         const struct rte_flow_item_ipv4 *mask = NULL;
380         const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4);
381         const struct rte_flow_item_ipv4 supp_mask = {
382                 .hdr = {
383                         .src_addr = 0xffffffff,
384                         .dst_addr = 0xffffffff,
385                         .next_proto_id = 0xff,
386                 }
387         };
388
389         rc = sfc_flow_parse_init(item,
390                                  (const void **)&spec,
391                                  (const void **)&mask,
392                                  &supp_mask,
393                                  &rte_flow_item_ipv4_mask,
394                                  sizeof(struct rte_flow_item_ipv4),
395                                  error);
396         if (rc != 0)
397                 return rc;
398
399         /*
400          * Filtering by IPv4 source and destination addresses requires
401          * the appropriate ETHER_TYPE in hardware filters
402          */
403         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
404                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
405                 efx_spec->efs_ether_type = ether_type_ipv4;
406         } else if (efx_spec->efs_ether_type != ether_type_ipv4) {
407                 rte_flow_error_set(error, EINVAL,
408                         RTE_FLOW_ERROR_TYPE_ITEM, item,
409                         "Ethertype in pattern with IPV4 item should be appropriate");
410                 return -rte_errno;
411         }
412
413         if (spec == NULL)
414                 return 0;
415
416         /*
417          * IPv4 addresses are in big-endian byte order in item and in
418          * efx_spec
419          */
420         if (mask->hdr.src_addr == supp_mask.hdr.src_addr) {
421                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
422                 efx_spec->efs_rem_host.eo_u32[0] = spec->hdr.src_addr;
423         } else if (mask->hdr.src_addr != 0) {
424                 goto fail_bad_mask;
425         }
426
427         if (mask->hdr.dst_addr == supp_mask.hdr.dst_addr) {
428                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
429                 efx_spec->efs_loc_host.eo_u32[0] = spec->hdr.dst_addr;
430         } else if (mask->hdr.dst_addr != 0) {
431                 goto fail_bad_mask;
432         }
433
434         if (mask->hdr.next_proto_id == supp_mask.hdr.next_proto_id) {
435                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
436                 efx_spec->efs_ip_proto = spec->hdr.next_proto_id;
437         } else if (mask->hdr.next_proto_id != 0) {
438                 goto fail_bad_mask;
439         }
440
441         return 0;
442
443 fail_bad_mask:
444         rte_flow_error_set(error, EINVAL,
445                            RTE_FLOW_ERROR_TYPE_ITEM, item,
446                            "Bad mask in the IPV4 pattern item");
447         return -rte_errno;
448 }
449
450 /**
451  * Convert IPv6 item to EFX filter specification.
452  *
453  * @param item[in]
454  *   Item specification. Only source and destination addresses and
455  *   next header fields are supported. If the mask is NULL, default
456  *   mask will be used. Ranging is not supported.
457  * @param efx_spec[in, out]
458  *   EFX filter specification to update.
459  * @param[out] error
460  *   Perform verbose error reporting if not NULL.
461  */
462 static int
463 sfc_flow_parse_ipv6(const struct rte_flow_item *item,
464                     efx_filter_spec_t *efx_spec,
465                     struct rte_flow_error *error)
466 {
467         int rc;
468         const struct rte_flow_item_ipv6 *spec = NULL;
469         const struct rte_flow_item_ipv6 *mask = NULL;
470         const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6);
471         const struct rte_flow_item_ipv6 supp_mask = {
472                 .hdr = {
473                         .src_addr = { 0xff, 0xff, 0xff, 0xff,
474                                       0xff, 0xff, 0xff, 0xff,
475                                       0xff, 0xff, 0xff, 0xff,
476                                       0xff, 0xff, 0xff, 0xff },
477                         .dst_addr = { 0xff, 0xff, 0xff, 0xff,
478                                       0xff, 0xff, 0xff, 0xff,
479                                       0xff, 0xff, 0xff, 0xff,
480                                       0xff, 0xff, 0xff, 0xff },
481                         .proto = 0xff,
482                 }
483         };
484
485         rc = sfc_flow_parse_init(item,
486                                  (const void **)&spec,
487                                  (const void **)&mask,
488                                  &supp_mask,
489                                  &rte_flow_item_ipv6_mask,
490                                  sizeof(struct rte_flow_item_ipv6),
491                                  error);
492         if (rc != 0)
493                 return rc;
494
495         /*
496          * Filtering by IPv6 source and destination addresses requires
497          * the appropriate ETHER_TYPE in hardware filters
498          */
499         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
500                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
501                 efx_spec->efs_ether_type = ether_type_ipv6;
502         } else if (efx_spec->efs_ether_type != ether_type_ipv6) {
503                 rte_flow_error_set(error, EINVAL,
504                         RTE_FLOW_ERROR_TYPE_ITEM, item,
505                         "Ethertype in pattern with IPV6 item should be appropriate");
506                 return -rte_errno;
507         }
508
509         if (spec == NULL)
510                 return 0;
511
512         /*
513          * IPv6 addresses are in big-endian byte order in item and in
514          * efx_spec
515          */
516         if (memcmp(mask->hdr.src_addr, supp_mask.hdr.src_addr,
517                    sizeof(mask->hdr.src_addr)) == 0) {
518                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
519
520                 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) !=
521                                  sizeof(spec->hdr.src_addr));
522                 rte_memcpy(&efx_spec->efs_rem_host, spec->hdr.src_addr,
523                            sizeof(efx_spec->efs_rem_host));
524         } else if (!sfc_flow_is_zero(mask->hdr.src_addr,
525                                      sizeof(mask->hdr.src_addr))) {
526                 goto fail_bad_mask;
527         }
528
529         if (memcmp(mask->hdr.dst_addr, supp_mask.hdr.dst_addr,
530                    sizeof(mask->hdr.dst_addr)) == 0) {
531                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
532
533                 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) !=
534                                  sizeof(spec->hdr.dst_addr));
535                 rte_memcpy(&efx_spec->efs_loc_host, spec->hdr.dst_addr,
536                            sizeof(efx_spec->efs_loc_host));
537         } else if (!sfc_flow_is_zero(mask->hdr.dst_addr,
538                                      sizeof(mask->hdr.dst_addr))) {
539                 goto fail_bad_mask;
540         }
541
542         if (mask->hdr.proto == supp_mask.hdr.proto) {
543                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
544                 efx_spec->efs_ip_proto = spec->hdr.proto;
545         } else if (mask->hdr.proto != 0) {
546                 goto fail_bad_mask;
547         }
548
549         return 0;
550
551 fail_bad_mask:
552         rte_flow_error_set(error, EINVAL,
553                            RTE_FLOW_ERROR_TYPE_ITEM, item,
554                            "Bad mask in the IPV6 pattern item");
555         return -rte_errno;
556 }
557
558 /**
559  * Convert TCP item to EFX filter specification.
560  *
561  * @param item[in]
562  *   Item specification. Only source and destination ports fields
563  *   are supported. If the mask is NULL, default mask will be used.
564  *   Ranging is not supported.
565  * @param efx_spec[in, out]
566  *   EFX filter specification to update.
567  * @param[out] error
568  *   Perform verbose error reporting if not NULL.
569  */
570 static int
571 sfc_flow_parse_tcp(const struct rte_flow_item *item,
572                    efx_filter_spec_t *efx_spec,
573                    struct rte_flow_error *error)
574 {
575         int rc;
576         const struct rte_flow_item_tcp *spec = NULL;
577         const struct rte_flow_item_tcp *mask = NULL;
578         const struct rte_flow_item_tcp supp_mask = {
579                 .hdr = {
580                         .src_port = 0xffff,
581                         .dst_port = 0xffff,
582                 }
583         };
584
585         rc = sfc_flow_parse_init(item,
586                                  (const void **)&spec,
587                                  (const void **)&mask,
588                                  &supp_mask,
589                                  &rte_flow_item_tcp_mask,
590                                  sizeof(struct rte_flow_item_tcp),
591                                  error);
592         if (rc != 0)
593                 return rc;
594
595         /*
596          * Filtering by TCP source and destination ports requires
597          * the appropriate IP_PROTO in hardware filters
598          */
599         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
600                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
601                 efx_spec->efs_ip_proto = EFX_IPPROTO_TCP;
602         } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_TCP) {
603                 rte_flow_error_set(error, EINVAL,
604                         RTE_FLOW_ERROR_TYPE_ITEM, item,
605                         "IP proto in pattern with TCP item should be appropriate");
606                 return -rte_errno;
607         }
608
609         if (spec == NULL)
610                 return 0;
611
612         /*
613          * Source and destination ports are in big-endian byte order in item and
614          * in little-endian in efx_spec, so byte swap is used
615          */
616         if (mask->hdr.src_port == supp_mask.hdr.src_port) {
617                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
618                 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
619         } else if (mask->hdr.src_port != 0) {
620                 goto fail_bad_mask;
621         }
622
623         if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
624                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
625                 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
626         } else if (mask->hdr.dst_port != 0) {
627                 goto fail_bad_mask;
628         }
629
630         return 0;
631
632 fail_bad_mask:
633         rte_flow_error_set(error, EINVAL,
634                            RTE_FLOW_ERROR_TYPE_ITEM, item,
635                            "Bad mask in the TCP pattern item");
636         return -rte_errno;
637 }
638
639 /**
640  * Convert UDP item to EFX filter specification.
641  *
642  * @param item[in]
643  *   Item specification. Only source and destination ports fields
644  *   are supported. If the mask is NULL, default mask will be used.
645  *   Ranging is not supported.
646  * @param efx_spec[in, out]
647  *   EFX filter specification to update.
648  * @param[out] error
649  *   Perform verbose error reporting if not NULL.
650  */
651 static int
652 sfc_flow_parse_udp(const struct rte_flow_item *item,
653                    efx_filter_spec_t *efx_spec,
654                    struct rte_flow_error *error)
655 {
656         int rc;
657         const struct rte_flow_item_udp *spec = NULL;
658         const struct rte_flow_item_udp *mask = NULL;
659         const struct rte_flow_item_udp supp_mask = {
660                 .hdr = {
661                         .src_port = 0xffff,
662                         .dst_port = 0xffff,
663                 }
664         };
665
666         rc = sfc_flow_parse_init(item,
667                                  (const void **)&spec,
668                                  (const void **)&mask,
669                                  &supp_mask,
670                                  &rte_flow_item_udp_mask,
671                                  sizeof(struct rte_flow_item_udp),
672                                  error);
673         if (rc != 0)
674                 return rc;
675
676         /*
677          * Filtering by UDP source and destination ports requires
678          * the appropriate IP_PROTO in hardware filters
679          */
680         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
681                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
682                 efx_spec->efs_ip_proto = EFX_IPPROTO_UDP;
683         } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_UDP) {
684                 rte_flow_error_set(error, EINVAL,
685                         RTE_FLOW_ERROR_TYPE_ITEM, item,
686                         "IP proto in pattern with UDP item should be appropriate");
687                 return -rte_errno;
688         }
689
690         if (spec == NULL)
691                 return 0;
692
693         /*
694          * Source and destination ports are in big-endian byte order in item and
695          * in little-endian in efx_spec, so byte swap is used
696          */
697         if (mask->hdr.src_port == supp_mask.hdr.src_port) {
698                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
699                 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
700         } else if (mask->hdr.src_port != 0) {
701                 goto fail_bad_mask;
702         }
703
704         if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
705                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
706                 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
707         } else if (mask->hdr.dst_port != 0) {
708                 goto fail_bad_mask;
709         }
710
711         return 0;
712
713 fail_bad_mask:
714         rte_flow_error_set(error, EINVAL,
715                            RTE_FLOW_ERROR_TYPE_ITEM, item,
716                            "Bad mask in the UDP pattern item");
717         return -rte_errno;
718 }
719
720 static const struct sfc_flow_item sfc_flow_items[] = {
721         {
722                 .type = RTE_FLOW_ITEM_TYPE_VOID,
723                 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
724                 .layer = SFC_FLOW_ITEM_ANY_LAYER,
725                 .parse = sfc_flow_parse_void,
726         },
727         {
728                 .type = RTE_FLOW_ITEM_TYPE_ETH,
729                 .prev_layer = SFC_FLOW_ITEM_START_LAYER,
730                 .layer = SFC_FLOW_ITEM_L2,
731                 .parse = sfc_flow_parse_eth,
732         },
733         {
734                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
735                 .prev_layer = SFC_FLOW_ITEM_L2,
736                 .layer = SFC_FLOW_ITEM_L2,
737                 .parse = sfc_flow_parse_vlan,
738         },
739         {
740                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
741                 .prev_layer = SFC_FLOW_ITEM_L2,
742                 .layer = SFC_FLOW_ITEM_L3,
743                 .parse = sfc_flow_parse_ipv4,
744         },
745         {
746                 .type = RTE_FLOW_ITEM_TYPE_IPV6,
747                 .prev_layer = SFC_FLOW_ITEM_L2,
748                 .layer = SFC_FLOW_ITEM_L3,
749                 .parse = sfc_flow_parse_ipv6,
750         },
751         {
752                 .type = RTE_FLOW_ITEM_TYPE_TCP,
753                 .prev_layer = SFC_FLOW_ITEM_L3,
754                 .layer = SFC_FLOW_ITEM_L4,
755                 .parse = sfc_flow_parse_tcp,
756         },
757         {
758                 .type = RTE_FLOW_ITEM_TYPE_UDP,
759                 .prev_layer = SFC_FLOW_ITEM_L3,
760                 .layer = SFC_FLOW_ITEM_L4,
761                 .parse = sfc_flow_parse_udp,
762         },
763 };
764
765 /*
766  * Protocol-independent flow API support
767  */
768 static int
769 sfc_flow_parse_attr(const struct rte_flow_attr *attr,
770                     struct rte_flow *flow,
771                     struct rte_flow_error *error)
772 {
773         if (attr == NULL) {
774                 rte_flow_error_set(error, EINVAL,
775                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
776                                    "NULL attribute");
777                 return -rte_errno;
778         }
779         if (attr->group != 0) {
780                 rte_flow_error_set(error, ENOTSUP,
781                                    RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr,
782                                    "Groups are not supported");
783                 return -rte_errno;
784         }
785         if (attr->priority != 0) {
786                 rte_flow_error_set(error, ENOTSUP,
787                                    RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr,
788                                    "Priorities are not supported");
789                 return -rte_errno;
790         }
791         if (attr->egress != 0) {
792                 rte_flow_error_set(error, ENOTSUP,
793                                    RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr,
794                                    "Egress is not supported");
795                 return -rte_errno;
796         }
797         if (attr->ingress == 0) {
798                 rte_flow_error_set(error, ENOTSUP,
799                                    RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
800                                    "Only ingress is supported");
801                 return -rte_errno;
802         }
803
804         flow->spec.efs_flags |= EFX_FILTER_FLAG_RX;
805         flow->spec.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
806
807         return 0;
808 }
809
810 /* Get item from array sfc_flow_items */
811 static const struct sfc_flow_item *
812 sfc_flow_get_item(enum rte_flow_item_type type)
813 {
814         unsigned int i;
815
816         for (i = 0; i < RTE_DIM(sfc_flow_items); i++)
817                 if (sfc_flow_items[i].type == type)
818                         return &sfc_flow_items[i];
819
820         return NULL;
821 }
822
823 static int
824 sfc_flow_parse_pattern(const struct rte_flow_item pattern[],
825                        struct rte_flow *flow,
826                        struct rte_flow_error *error)
827 {
828         int rc;
829         unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER;
830         const struct sfc_flow_item *item;
831
832         if (pattern == NULL) {
833                 rte_flow_error_set(error, EINVAL,
834                                    RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
835                                    "NULL pattern");
836                 return -rte_errno;
837         }
838
839         for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
840                 item = sfc_flow_get_item(pattern->type);
841                 if (item == NULL) {
842                         rte_flow_error_set(error, ENOTSUP,
843                                            RTE_FLOW_ERROR_TYPE_ITEM, pattern,
844                                            "Unsupported pattern item");
845                         return -rte_errno;
846                 }
847
848                 /*
849                  * Omitting one or several protocol layers at the beginning
850                  * of pattern is supported
851                  */
852                 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
853                     prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
854                     item->prev_layer != prev_layer) {
855                         rte_flow_error_set(error, ENOTSUP,
856                                            RTE_FLOW_ERROR_TYPE_ITEM, pattern,
857                                            "Unexpected sequence of pattern items");
858                         return -rte_errno;
859                 }
860
861                 rc = item->parse(pattern, &flow->spec, error);
862                 if (rc != 0)
863                         return rc;
864
865                 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER)
866                         prev_layer = item->layer;
867         }
868
869         return 0;
870 }
871
872 static int
873 sfc_flow_parse_queue(struct sfc_adapter *sa,
874                      const struct rte_flow_action_queue *queue,
875                      struct rte_flow *flow)
876 {
877         struct sfc_rxq *rxq;
878
879         if (queue->index >= sa->rxq_count)
880                 return -EINVAL;
881
882         rxq = sa->rxq_info[queue->index].rxq;
883         flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index;
884
885         return 0;
886 }
887
888 #if EFSYS_OPT_RX_SCALE
889 static int
890 sfc_flow_parse_rss(struct sfc_adapter *sa,
891                    const struct rte_flow_action_rss *rss,
892                    struct rte_flow *flow)
893 {
894         unsigned int rxq_sw_index;
895         struct sfc_rxq *rxq;
896         unsigned int rxq_hw_index_min;
897         unsigned int rxq_hw_index_max;
898         const struct rte_eth_rss_conf *rss_conf = rss->rss_conf;
899         uint64_t rss_hf;
900         uint8_t *rss_key = NULL;
901         struct sfc_flow_rss *sfc_rss_conf = &flow->rss_conf;
902         unsigned int i;
903
904         if (rss->num == 0)
905                 return -EINVAL;
906
907         rxq_sw_index = sa->rxq_count - 1;
908         rxq = sa->rxq_info[rxq_sw_index].rxq;
909         rxq_hw_index_min = rxq->hw_index;
910         rxq_hw_index_max = 0;
911
912         for (i = 0; i < rss->num; ++i) {
913                 rxq_sw_index = rss->queue[i];
914
915                 if (rxq_sw_index >= sa->rxq_count)
916                         return -EINVAL;
917
918                 rxq = sa->rxq_info[rxq_sw_index].rxq;
919
920                 if (rxq->hw_index < rxq_hw_index_min)
921                         rxq_hw_index_min = rxq->hw_index;
922
923                 if (rxq->hw_index > rxq_hw_index_max)
924                         rxq_hw_index_max = rxq->hw_index;
925         }
926
927         rss_hf = (rss_conf != NULL) ? rss_conf->rss_hf : SFC_RSS_OFFLOADS;
928         if ((rss_hf & ~SFC_RSS_OFFLOADS) != 0)
929                 return -EINVAL;
930
931         if (rss_conf != NULL) {
932                 if (rss_conf->rss_key_len != sizeof(sa->rss_key))
933                         return -EINVAL;
934
935                 rss_key = rss_conf->rss_key;
936         } else {
937                 rss_key = sa->rss_key;
938         }
939
940         flow->rss = B_TRUE;
941
942         sfc_rss_conf->rxq_hw_index_min = rxq_hw_index_min;
943         sfc_rss_conf->rxq_hw_index_max = rxq_hw_index_max;
944         sfc_rss_conf->rss_hash_types = sfc_rte_to_efx_hash_type(rss_hf);
945         rte_memcpy(sfc_rss_conf->rss_key, rss_key, sizeof(sa->rss_key));
946
947         for (i = 0; i < RTE_DIM(sfc_rss_conf->rss_tbl); ++i) {
948                 unsigned int rxq_sw_index = rss->queue[i % rss->num];
949                 struct sfc_rxq *rxq = sa->rxq_info[rxq_sw_index].rxq;
950
951                 sfc_rss_conf->rss_tbl[i] = rxq->hw_index - rxq_hw_index_min;
952         }
953
954         return 0;
955 }
956 #endif /* EFSYS_OPT_RX_SCALE */
957
958 static int
959 sfc_flow_filter_insert(struct sfc_adapter *sa,
960                        struct rte_flow *flow)
961 {
962         efx_filter_spec_t *spec = &flow->spec;
963
964 #if EFSYS_OPT_RX_SCALE
965         struct sfc_flow_rss *rss = &flow->rss_conf;
966         int rc = 0;
967
968         if (flow->rss) {
969                 unsigned int rss_spread = MIN(rss->rxq_hw_index_max -
970                                               rss->rxq_hw_index_min + 1,
971                                               EFX_MAXRSS);
972
973                 rc = efx_rx_scale_context_alloc(sa->nic,
974                                                 EFX_RX_SCALE_EXCLUSIVE,
975                                                 rss_spread,
976                                                 &spec->efs_rss_context);
977                 if (rc != 0)
978                         goto fail_scale_context_alloc;
979
980                 rc = efx_rx_scale_mode_set(sa->nic, spec->efs_rss_context,
981                                            EFX_RX_HASHALG_TOEPLITZ,
982                                            rss->rss_hash_types, B_TRUE);
983                 if (rc != 0)
984                         goto fail_scale_mode_set;
985
986                 rc = efx_rx_scale_key_set(sa->nic, spec->efs_rss_context,
987                                           rss->rss_key,
988                                           sizeof(sa->rss_key));
989                 if (rc != 0)
990                         goto fail_scale_key_set;
991
992                 spec->efs_dmaq_id = rss->rxq_hw_index_min;
993                 spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS;
994         }
995
996         rc = efx_filter_insert(sa->nic, spec);
997         if (rc != 0)
998                 goto fail_filter_insert;
999
1000         if (flow->rss) {
1001                 /*
1002                  * Scale table is set after filter insertion because
1003                  * the table entries are relative to the base RxQ ID
1004                  * and the latter is submitted to the HW by means of
1005                  * inserting a filter, so by the time of the request
1006                  * the HW knows all the information needed to verify
1007                  * the table entries, and the operation will succeed
1008                  */
1009                 rc = efx_rx_scale_tbl_set(sa->nic, spec->efs_rss_context,
1010                                           rss->rss_tbl, RTE_DIM(rss->rss_tbl));
1011                 if (rc != 0)
1012                         goto fail_scale_tbl_set;
1013         }
1014
1015         return 0;
1016
1017 fail_scale_tbl_set:
1018         efx_filter_remove(sa->nic, spec);
1019
1020 fail_filter_insert:
1021 fail_scale_key_set:
1022 fail_scale_mode_set:
1023         if (flow->rss)
1024                 efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
1025
1026 fail_scale_context_alloc:
1027         return rc;
1028 #else /* !EFSYS_OPT_RX_SCALE */
1029         return efx_filter_insert(sa->nic, spec);
1030 #endif /* EFSYS_OPT_RX_SCALE */
1031 }
1032
1033 static int
1034 sfc_flow_filter_remove(struct sfc_adapter *sa,
1035                        struct rte_flow *flow)
1036 {
1037         efx_filter_spec_t *spec = &flow->spec;
1038         int rc = 0;
1039
1040         rc = efx_filter_remove(sa->nic, spec);
1041         if (rc != 0)
1042                 return rc;
1043
1044 #if EFSYS_OPT_RX_SCALE
1045         if (flow->rss)
1046                 rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
1047 #endif /* EFSYS_OPT_RX_SCALE */
1048
1049         return rc;
1050 }
1051
1052 static int
1053 sfc_flow_parse_actions(struct sfc_adapter *sa,
1054                        const struct rte_flow_action actions[],
1055                        struct rte_flow *flow,
1056                        struct rte_flow_error *error)
1057 {
1058         int rc;
1059         boolean_t is_specified = B_FALSE;
1060
1061         if (actions == NULL) {
1062                 rte_flow_error_set(error, EINVAL,
1063                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
1064                                    "NULL actions");
1065                 return -rte_errno;
1066         }
1067
1068         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1069                 switch (actions->type) {
1070                 case RTE_FLOW_ACTION_TYPE_VOID:
1071                         break;
1072
1073                 case RTE_FLOW_ACTION_TYPE_QUEUE:
1074                         rc = sfc_flow_parse_queue(sa, actions->conf, flow);
1075                         if (rc != 0) {
1076                                 rte_flow_error_set(error, EINVAL,
1077                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
1078                                         "Bad QUEUE action");
1079                                 return -rte_errno;
1080                         }
1081
1082                         is_specified = B_TRUE;
1083                         break;
1084
1085 #if EFSYS_OPT_RX_SCALE
1086                 case RTE_FLOW_ACTION_TYPE_RSS:
1087                         rc = sfc_flow_parse_rss(sa, actions->conf, flow);
1088                         if (rc != 0) {
1089                                 rte_flow_error_set(error, rc,
1090                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
1091                                         "Bad RSS action");
1092                                 return -rte_errno;
1093                         }
1094
1095                         is_specified = B_TRUE;
1096                         break;
1097 #endif /* EFSYS_OPT_RX_SCALE */
1098
1099                 default:
1100                         rte_flow_error_set(error, ENOTSUP,
1101                                            RTE_FLOW_ERROR_TYPE_ACTION, actions,
1102                                            "Action is not supported");
1103                         return -rte_errno;
1104                 }
1105         }
1106
1107         if (!is_specified) {
1108                 rte_flow_error_set(error, EINVAL,
1109                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions,
1110                                    "Action is unspecified");
1111                 return -rte_errno;
1112         }
1113
1114         return 0;
1115 }
1116
1117 static int
1118 sfc_flow_parse(struct rte_eth_dev *dev,
1119                const struct rte_flow_attr *attr,
1120                const struct rte_flow_item pattern[],
1121                const struct rte_flow_action actions[],
1122                struct rte_flow *flow,
1123                struct rte_flow_error *error)
1124 {
1125         struct sfc_adapter *sa = dev->data->dev_private;
1126         int rc;
1127
1128         rc = sfc_flow_parse_attr(attr, flow, error);
1129         if (rc != 0)
1130                 goto fail_bad_value;
1131
1132         rc = sfc_flow_parse_pattern(pattern, flow, error);
1133         if (rc != 0)
1134                 goto fail_bad_value;
1135
1136         rc = sfc_flow_parse_actions(sa, actions, flow, error);
1137         if (rc != 0)
1138                 goto fail_bad_value;
1139
1140         if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) {
1141                 rte_flow_error_set(error, ENOTSUP,
1142                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1143                                    "Flow rule pattern is not supported");
1144                 return -rte_errno;
1145         }
1146
1147 fail_bad_value:
1148         return rc;
1149 }
1150
1151 static int
1152 sfc_flow_validate(struct rte_eth_dev *dev,
1153                   const struct rte_flow_attr *attr,
1154                   const struct rte_flow_item pattern[],
1155                   const struct rte_flow_action actions[],
1156                   struct rte_flow_error *error)
1157 {
1158         struct rte_flow flow;
1159
1160         memset(&flow, 0, sizeof(flow));
1161
1162         return sfc_flow_parse(dev, attr, pattern, actions, &flow, error);
1163 }
1164
1165 static struct rte_flow *
1166 sfc_flow_create(struct rte_eth_dev *dev,
1167                 const struct rte_flow_attr *attr,
1168                 const struct rte_flow_item pattern[],
1169                 const struct rte_flow_action actions[],
1170                 struct rte_flow_error *error)
1171 {
1172         struct sfc_adapter *sa = dev->data->dev_private;
1173         struct rte_flow *flow = NULL;
1174         int rc;
1175
1176         flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0);
1177         if (flow == NULL) {
1178                 rte_flow_error_set(error, ENOMEM,
1179                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1180                                    "Failed to allocate memory");
1181                 goto fail_no_mem;
1182         }
1183
1184         rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
1185         if (rc != 0)
1186                 goto fail_bad_value;
1187
1188         TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries);
1189
1190         sfc_adapter_lock(sa);
1191
1192         if (sa->state == SFC_ADAPTER_STARTED) {
1193                 rc = sfc_flow_filter_insert(sa, flow);
1194                 if (rc != 0) {
1195                         rte_flow_error_set(error, rc,
1196                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1197                                 "Failed to insert filter");
1198                         goto fail_filter_insert;
1199                 }
1200         }
1201
1202         sfc_adapter_unlock(sa);
1203
1204         return flow;
1205
1206 fail_filter_insert:
1207         TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1208
1209 fail_bad_value:
1210         rte_free(flow);
1211         sfc_adapter_unlock(sa);
1212
1213 fail_no_mem:
1214         return NULL;
1215 }
1216
1217 static int
1218 sfc_flow_remove(struct sfc_adapter *sa,
1219                 struct rte_flow *flow,
1220                 struct rte_flow_error *error)
1221 {
1222         int rc = 0;
1223
1224         SFC_ASSERT(sfc_adapter_is_locked(sa));
1225
1226         if (sa->state == SFC_ADAPTER_STARTED) {
1227                 rc = sfc_flow_filter_remove(sa, flow);
1228                 if (rc != 0)
1229                         rte_flow_error_set(error, rc,
1230                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1231                                 "Failed to destroy flow rule");
1232         }
1233
1234         TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1235         rte_free(flow);
1236
1237         return rc;
1238 }
1239
1240 static int
1241 sfc_flow_destroy(struct rte_eth_dev *dev,
1242                  struct rte_flow *flow,
1243                  struct rte_flow_error *error)
1244 {
1245         struct sfc_adapter *sa = dev->data->dev_private;
1246         struct rte_flow *flow_ptr;
1247         int rc = EINVAL;
1248
1249         sfc_adapter_lock(sa);
1250
1251         TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) {
1252                 if (flow_ptr == flow)
1253                         rc = 0;
1254         }
1255         if (rc != 0) {
1256                 rte_flow_error_set(error, rc,
1257                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1258                                    "Failed to find flow rule to destroy");
1259                 goto fail_bad_value;
1260         }
1261
1262         rc = sfc_flow_remove(sa, flow, error);
1263
1264 fail_bad_value:
1265         sfc_adapter_unlock(sa);
1266
1267         return -rc;
1268 }
1269
1270 static int
1271 sfc_flow_flush(struct rte_eth_dev *dev,
1272                struct rte_flow_error *error)
1273 {
1274         struct sfc_adapter *sa = dev->data->dev_private;
1275         struct rte_flow *flow;
1276         int rc = 0;
1277         int ret = 0;
1278
1279         sfc_adapter_lock(sa);
1280
1281         while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1282                 rc = sfc_flow_remove(sa, flow, error);
1283                 if (rc != 0)
1284                         ret = rc;
1285         }
1286
1287         sfc_adapter_unlock(sa);
1288
1289         return -ret;
1290 }
1291
1292 static int
1293 sfc_flow_isolate(struct rte_eth_dev *dev, int enable,
1294                  struct rte_flow_error *error)
1295 {
1296         struct sfc_adapter *sa = dev->data->dev_private;
1297         struct sfc_port *port = &sa->port;
1298         int ret = 0;
1299
1300         sfc_adapter_lock(sa);
1301         if (sa->state != SFC_ADAPTER_INITIALIZED) {
1302                 rte_flow_error_set(error, EBUSY,
1303                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1304                                    NULL, "please close the port first");
1305                 ret = -rte_errno;
1306         } else {
1307                 port->isolated = (enable) ? B_TRUE : B_FALSE;
1308         }
1309         sfc_adapter_unlock(sa);
1310
1311         return ret;
1312 }
1313
1314 const struct rte_flow_ops sfc_flow_ops = {
1315         .validate = sfc_flow_validate,
1316         .create = sfc_flow_create,
1317         .destroy = sfc_flow_destroy,
1318         .flush = sfc_flow_flush,
1319         .query = NULL,
1320         .isolate = sfc_flow_isolate,
1321 };
1322
1323 void
1324 sfc_flow_init(struct sfc_adapter *sa)
1325 {
1326         SFC_ASSERT(sfc_adapter_is_locked(sa));
1327
1328         TAILQ_INIT(&sa->filter.flow_list);
1329 }
1330
1331 void
1332 sfc_flow_fini(struct sfc_adapter *sa)
1333 {
1334         struct rte_flow *flow;
1335
1336         SFC_ASSERT(sfc_adapter_is_locked(sa));
1337
1338         while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1339                 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1340                 rte_free(flow);
1341         }
1342 }
1343
1344 void
1345 sfc_flow_stop(struct sfc_adapter *sa)
1346 {
1347         struct rte_flow *flow;
1348
1349         SFC_ASSERT(sfc_adapter_is_locked(sa));
1350
1351         TAILQ_FOREACH(flow, &sa->filter.flow_list, entries)
1352                 sfc_flow_filter_remove(sa, flow);
1353 }
1354
1355 int
1356 sfc_flow_start(struct sfc_adapter *sa)
1357 {
1358         struct rte_flow *flow;
1359         int rc = 0;
1360
1361         sfc_log_init(sa, "entry");
1362
1363         SFC_ASSERT(sfc_adapter_is_locked(sa));
1364
1365         TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) {
1366                 rc = sfc_flow_filter_insert(sa, flow);
1367                 if (rc != 0)
1368                         goto fail_bad_flow;
1369         }
1370
1371         sfc_log_init(sa, "done");
1372
1373 fail_bad_flow:
1374         return rc;
1375 }