New upstream version 17.11.3
[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                 vid = rte_bswap16(spec->tci);
334
335                 if (!(efx_spec->efs_match_flags &
336                       EFX_FILTER_MATCH_OUTER_VID)) {
337                         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
338                         efx_spec->efs_outer_vid = vid;
339                 } else if (!(efx_spec->efs_match_flags &
340                              EFX_FILTER_MATCH_INNER_VID)) {
341                         efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID;
342                         efx_spec->efs_inner_vid = vid;
343                 } else {
344                         rte_flow_error_set(error, EINVAL,
345                                            RTE_FLOW_ERROR_TYPE_ITEM, item,
346                                            "More than two VLAN items");
347                         return -rte_errno;
348                 }
349         } else {
350                 rte_flow_error_set(error, EINVAL,
351                                    RTE_FLOW_ERROR_TYPE_ITEM, item,
352                                    "VLAN ID in TCI match is required");
353                 return -rte_errno;
354         }
355
356         return 0;
357 }
358
359 /**
360  * Convert IPv4 item to EFX filter specification.
361  *
362  * @param item[in]
363  *   Item specification. Only source and destination addresses and
364  *   protocol fields are supported. If the mask is NULL, default
365  *   mask will be used. Ranging is not supported.
366  * @param efx_spec[in, out]
367  *   EFX filter specification to update.
368  * @param[out] error
369  *   Perform verbose error reporting if not NULL.
370  */
371 static int
372 sfc_flow_parse_ipv4(const struct rte_flow_item *item,
373                     efx_filter_spec_t *efx_spec,
374                     struct rte_flow_error *error)
375 {
376         int rc;
377         const struct rte_flow_item_ipv4 *spec = NULL;
378         const struct rte_flow_item_ipv4 *mask = NULL;
379         const uint16_t ether_type_ipv4 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV4);
380         const struct rte_flow_item_ipv4 supp_mask = {
381                 .hdr = {
382                         .src_addr = 0xffffffff,
383                         .dst_addr = 0xffffffff,
384                         .next_proto_id = 0xff,
385                 }
386         };
387
388         rc = sfc_flow_parse_init(item,
389                                  (const void **)&spec,
390                                  (const void **)&mask,
391                                  &supp_mask,
392                                  &rte_flow_item_ipv4_mask,
393                                  sizeof(struct rte_flow_item_ipv4),
394                                  error);
395         if (rc != 0)
396                 return rc;
397
398         /*
399          * Filtering by IPv4 source and destination addresses requires
400          * the appropriate ETHER_TYPE in hardware filters
401          */
402         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
403                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
404                 efx_spec->efs_ether_type = ether_type_ipv4;
405         } else if (efx_spec->efs_ether_type != ether_type_ipv4) {
406                 rte_flow_error_set(error, EINVAL,
407                         RTE_FLOW_ERROR_TYPE_ITEM, item,
408                         "Ethertype in pattern with IPV4 item should be appropriate");
409                 return -rte_errno;
410         }
411
412         if (spec == NULL)
413                 return 0;
414
415         /*
416          * IPv4 addresses are in big-endian byte order in item and in
417          * efx_spec
418          */
419         if (mask->hdr.src_addr == supp_mask.hdr.src_addr) {
420                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
421                 efx_spec->efs_rem_host.eo_u32[0] = spec->hdr.src_addr;
422         } else if (mask->hdr.src_addr != 0) {
423                 goto fail_bad_mask;
424         }
425
426         if (mask->hdr.dst_addr == supp_mask.hdr.dst_addr) {
427                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
428                 efx_spec->efs_loc_host.eo_u32[0] = spec->hdr.dst_addr;
429         } else if (mask->hdr.dst_addr != 0) {
430                 goto fail_bad_mask;
431         }
432
433         if (mask->hdr.next_proto_id == supp_mask.hdr.next_proto_id) {
434                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
435                 efx_spec->efs_ip_proto = spec->hdr.next_proto_id;
436         } else if (mask->hdr.next_proto_id != 0) {
437                 goto fail_bad_mask;
438         }
439
440         return 0;
441
442 fail_bad_mask:
443         rte_flow_error_set(error, EINVAL,
444                            RTE_FLOW_ERROR_TYPE_ITEM, item,
445                            "Bad mask in the IPV4 pattern item");
446         return -rte_errno;
447 }
448
449 /**
450  * Convert IPv6 item to EFX filter specification.
451  *
452  * @param item[in]
453  *   Item specification. Only source and destination addresses and
454  *   next header 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_ipv6(const struct rte_flow_item *item,
463                     efx_filter_spec_t *efx_spec,
464                     struct rte_flow_error *error)
465 {
466         int rc;
467         const struct rte_flow_item_ipv6 *spec = NULL;
468         const struct rte_flow_item_ipv6 *mask = NULL;
469         const uint16_t ether_type_ipv6 = rte_cpu_to_le_16(EFX_ETHER_TYPE_IPV6);
470         const struct rte_flow_item_ipv6 supp_mask = {
471                 .hdr = {
472                         .src_addr = { 0xff, 0xff, 0xff, 0xff,
473                                       0xff, 0xff, 0xff, 0xff,
474                                       0xff, 0xff, 0xff, 0xff,
475                                       0xff, 0xff, 0xff, 0xff },
476                         .dst_addr = { 0xff, 0xff, 0xff, 0xff,
477                                       0xff, 0xff, 0xff, 0xff,
478                                       0xff, 0xff, 0xff, 0xff,
479                                       0xff, 0xff, 0xff, 0xff },
480                         .proto = 0xff,
481                 }
482         };
483
484         rc = sfc_flow_parse_init(item,
485                                  (const void **)&spec,
486                                  (const void **)&mask,
487                                  &supp_mask,
488                                  &rte_flow_item_ipv6_mask,
489                                  sizeof(struct rte_flow_item_ipv6),
490                                  error);
491         if (rc != 0)
492                 return rc;
493
494         /*
495          * Filtering by IPv6 source and destination addresses requires
496          * the appropriate ETHER_TYPE in hardware filters
497          */
498         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_ETHER_TYPE)) {
499                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
500                 efx_spec->efs_ether_type = ether_type_ipv6;
501         } else if (efx_spec->efs_ether_type != ether_type_ipv6) {
502                 rte_flow_error_set(error, EINVAL,
503                         RTE_FLOW_ERROR_TYPE_ITEM, item,
504                         "Ethertype in pattern with IPV6 item should be appropriate");
505                 return -rte_errno;
506         }
507
508         if (spec == NULL)
509                 return 0;
510
511         /*
512          * IPv6 addresses are in big-endian byte order in item and in
513          * efx_spec
514          */
515         if (memcmp(mask->hdr.src_addr, supp_mask.hdr.src_addr,
516                    sizeof(mask->hdr.src_addr)) == 0) {
517                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_HOST;
518
519                 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_rem_host) !=
520                                  sizeof(spec->hdr.src_addr));
521                 rte_memcpy(&efx_spec->efs_rem_host, spec->hdr.src_addr,
522                            sizeof(efx_spec->efs_rem_host));
523         } else if (!sfc_flow_is_zero(mask->hdr.src_addr,
524                                      sizeof(mask->hdr.src_addr))) {
525                 goto fail_bad_mask;
526         }
527
528         if (memcmp(mask->hdr.dst_addr, supp_mask.hdr.dst_addr,
529                    sizeof(mask->hdr.dst_addr)) == 0) {
530                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_HOST;
531
532                 RTE_BUILD_BUG_ON(sizeof(efx_spec->efs_loc_host) !=
533                                  sizeof(spec->hdr.dst_addr));
534                 rte_memcpy(&efx_spec->efs_loc_host, spec->hdr.dst_addr,
535                            sizeof(efx_spec->efs_loc_host));
536         } else if (!sfc_flow_is_zero(mask->hdr.dst_addr,
537                                      sizeof(mask->hdr.dst_addr))) {
538                 goto fail_bad_mask;
539         }
540
541         if (mask->hdr.proto == supp_mask.hdr.proto) {
542                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
543                 efx_spec->efs_ip_proto = spec->hdr.proto;
544         } else if (mask->hdr.proto != 0) {
545                 goto fail_bad_mask;
546         }
547
548         return 0;
549
550 fail_bad_mask:
551         rte_flow_error_set(error, EINVAL,
552                            RTE_FLOW_ERROR_TYPE_ITEM, item,
553                            "Bad mask in the IPV6 pattern item");
554         return -rte_errno;
555 }
556
557 /**
558  * Convert TCP item to EFX filter specification.
559  *
560  * @param item[in]
561  *   Item specification. Only source and destination ports fields
562  *   are supported. If the mask is NULL, default mask will be used.
563  *   Ranging is not supported.
564  * @param efx_spec[in, out]
565  *   EFX filter specification to update.
566  * @param[out] error
567  *   Perform verbose error reporting if not NULL.
568  */
569 static int
570 sfc_flow_parse_tcp(const struct rte_flow_item *item,
571                    efx_filter_spec_t *efx_spec,
572                    struct rte_flow_error *error)
573 {
574         int rc;
575         const struct rte_flow_item_tcp *spec = NULL;
576         const struct rte_flow_item_tcp *mask = NULL;
577         const struct rte_flow_item_tcp supp_mask = {
578                 .hdr = {
579                         .src_port = 0xffff,
580                         .dst_port = 0xffff,
581                 }
582         };
583
584         rc = sfc_flow_parse_init(item,
585                                  (const void **)&spec,
586                                  (const void **)&mask,
587                                  &supp_mask,
588                                  &rte_flow_item_tcp_mask,
589                                  sizeof(struct rte_flow_item_tcp),
590                                  error);
591         if (rc != 0)
592                 return rc;
593
594         /*
595          * Filtering by TCP source and destination ports requires
596          * the appropriate IP_PROTO in hardware filters
597          */
598         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
599                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
600                 efx_spec->efs_ip_proto = EFX_IPPROTO_TCP;
601         } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_TCP) {
602                 rte_flow_error_set(error, EINVAL,
603                         RTE_FLOW_ERROR_TYPE_ITEM, item,
604                         "IP proto in pattern with TCP item should be appropriate");
605                 return -rte_errno;
606         }
607
608         if (spec == NULL)
609                 return 0;
610
611         /*
612          * Source and destination ports are in big-endian byte order in item and
613          * in little-endian in efx_spec, so byte swap is used
614          */
615         if (mask->hdr.src_port == supp_mask.hdr.src_port) {
616                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
617                 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
618         } else if (mask->hdr.src_port != 0) {
619                 goto fail_bad_mask;
620         }
621
622         if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
623                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
624                 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
625         } else if (mask->hdr.dst_port != 0) {
626                 goto fail_bad_mask;
627         }
628
629         return 0;
630
631 fail_bad_mask:
632         rte_flow_error_set(error, EINVAL,
633                            RTE_FLOW_ERROR_TYPE_ITEM, item,
634                            "Bad mask in the TCP pattern item");
635         return -rte_errno;
636 }
637
638 /**
639  * Convert UDP item to EFX filter specification.
640  *
641  * @param item[in]
642  *   Item specification. Only source and destination ports fields
643  *   are supported. If the mask is NULL, default mask will be used.
644  *   Ranging is not supported.
645  * @param efx_spec[in, out]
646  *   EFX filter specification to update.
647  * @param[out] error
648  *   Perform verbose error reporting if not NULL.
649  */
650 static int
651 sfc_flow_parse_udp(const struct rte_flow_item *item,
652                    efx_filter_spec_t *efx_spec,
653                    struct rte_flow_error *error)
654 {
655         int rc;
656         const struct rte_flow_item_udp *spec = NULL;
657         const struct rte_flow_item_udp *mask = NULL;
658         const struct rte_flow_item_udp supp_mask = {
659                 .hdr = {
660                         .src_port = 0xffff,
661                         .dst_port = 0xffff,
662                 }
663         };
664
665         rc = sfc_flow_parse_init(item,
666                                  (const void **)&spec,
667                                  (const void **)&mask,
668                                  &supp_mask,
669                                  &rte_flow_item_udp_mask,
670                                  sizeof(struct rte_flow_item_udp),
671                                  error);
672         if (rc != 0)
673                 return rc;
674
675         /*
676          * Filtering by UDP source and destination ports requires
677          * the appropriate IP_PROTO in hardware filters
678          */
679         if (!(efx_spec->efs_match_flags & EFX_FILTER_MATCH_IP_PROTO)) {
680                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_IP_PROTO;
681                 efx_spec->efs_ip_proto = EFX_IPPROTO_UDP;
682         } else if (efx_spec->efs_ip_proto != EFX_IPPROTO_UDP) {
683                 rte_flow_error_set(error, EINVAL,
684                         RTE_FLOW_ERROR_TYPE_ITEM, item,
685                         "IP proto in pattern with UDP item should be appropriate");
686                 return -rte_errno;
687         }
688
689         if (spec == NULL)
690                 return 0;
691
692         /*
693          * Source and destination ports are in big-endian byte order in item and
694          * in little-endian in efx_spec, so byte swap is used
695          */
696         if (mask->hdr.src_port == supp_mask.hdr.src_port) {
697                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_REM_PORT;
698                 efx_spec->efs_rem_port = rte_bswap16(spec->hdr.src_port);
699         } else if (mask->hdr.src_port != 0) {
700                 goto fail_bad_mask;
701         }
702
703         if (mask->hdr.dst_port == supp_mask.hdr.dst_port) {
704                 efx_spec->efs_match_flags |= EFX_FILTER_MATCH_LOC_PORT;
705                 efx_spec->efs_loc_port = rte_bswap16(spec->hdr.dst_port);
706         } else if (mask->hdr.dst_port != 0) {
707                 goto fail_bad_mask;
708         }
709
710         return 0;
711
712 fail_bad_mask:
713         rte_flow_error_set(error, EINVAL,
714                            RTE_FLOW_ERROR_TYPE_ITEM, item,
715                            "Bad mask in the UDP pattern item");
716         return -rte_errno;
717 }
718
719 static const struct sfc_flow_item sfc_flow_items[] = {
720         {
721                 .type = RTE_FLOW_ITEM_TYPE_VOID,
722                 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
723                 .layer = SFC_FLOW_ITEM_ANY_LAYER,
724                 .parse = sfc_flow_parse_void,
725         },
726         {
727                 .type = RTE_FLOW_ITEM_TYPE_ETH,
728                 .prev_layer = SFC_FLOW_ITEM_START_LAYER,
729                 .layer = SFC_FLOW_ITEM_L2,
730                 .parse = sfc_flow_parse_eth,
731         },
732         {
733                 .type = RTE_FLOW_ITEM_TYPE_VLAN,
734                 .prev_layer = SFC_FLOW_ITEM_L2,
735                 .layer = SFC_FLOW_ITEM_L2,
736                 .parse = sfc_flow_parse_vlan,
737         },
738         {
739                 .type = RTE_FLOW_ITEM_TYPE_IPV4,
740                 .prev_layer = SFC_FLOW_ITEM_L2,
741                 .layer = SFC_FLOW_ITEM_L3,
742                 .parse = sfc_flow_parse_ipv4,
743         },
744         {
745                 .type = RTE_FLOW_ITEM_TYPE_IPV6,
746                 .prev_layer = SFC_FLOW_ITEM_L2,
747                 .layer = SFC_FLOW_ITEM_L3,
748                 .parse = sfc_flow_parse_ipv6,
749         },
750         {
751                 .type = RTE_FLOW_ITEM_TYPE_TCP,
752                 .prev_layer = SFC_FLOW_ITEM_L3,
753                 .layer = SFC_FLOW_ITEM_L4,
754                 .parse = sfc_flow_parse_tcp,
755         },
756         {
757                 .type = RTE_FLOW_ITEM_TYPE_UDP,
758                 .prev_layer = SFC_FLOW_ITEM_L3,
759                 .layer = SFC_FLOW_ITEM_L4,
760                 .parse = sfc_flow_parse_udp,
761         },
762 };
763
764 /*
765  * Protocol-independent flow API support
766  */
767 static int
768 sfc_flow_parse_attr(const struct rte_flow_attr *attr,
769                     struct rte_flow *flow,
770                     struct rte_flow_error *error)
771 {
772         if (attr == NULL) {
773                 rte_flow_error_set(error, EINVAL,
774                                    RTE_FLOW_ERROR_TYPE_ATTR, NULL,
775                                    "NULL attribute");
776                 return -rte_errno;
777         }
778         if (attr->group != 0) {
779                 rte_flow_error_set(error, ENOTSUP,
780                                    RTE_FLOW_ERROR_TYPE_ATTR_GROUP, attr,
781                                    "Groups are not supported");
782                 return -rte_errno;
783         }
784         if (attr->priority != 0) {
785                 rte_flow_error_set(error, ENOTSUP,
786                                    RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, attr,
787                                    "Priorities are not supported");
788                 return -rte_errno;
789         }
790         if (attr->egress != 0) {
791                 rte_flow_error_set(error, ENOTSUP,
792                                    RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, attr,
793                                    "Egress is not supported");
794                 return -rte_errno;
795         }
796         if (attr->ingress == 0) {
797                 rte_flow_error_set(error, ENOTSUP,
798                                    RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, attr,
799                                    "Only ingress is supported");
800                 return -rte_errno;
801         }
802
803         flow->spec.efs_flags |= EFX_FILTER_FLAG_RX;
804         flow->spec.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
805
806         return 0;
807 }
808
809 /* Get item from array sfc_flow_items */
810 static const struct sfc_flow_item *
811 sfc_flow_get_item(enum rte_flow_item_type type)
812 {
813         unsigned int i;
814
815         for (i = 0; i < RTE_DIM(sfc_flow_items); i++)
816                 if (sfc_flow_items[i].type == type)
817                         return &sfc_flow_items[i];
818
819         return NULL;
820 }
821
822 static int
823 sfc_flow_parse_pattern(const struct rte_flow_item pattern[],
824                        struct rte_flow *flow,
825                        struct rte_flow_error *error)
826 {
827         int rc;
828         unsigned int prev_layer = SFC_FLOW_ITEM_ANY_LAYER;
829         const struct sfc_flow_item *item;
830
831         if (pattern == NULL) {
832                 rte_flow_error_set(error, EINVAL,
833                                    RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
834                                    "NULL pattern");
835                 return -rte_errno;
836         }
837
838         for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) {
839                 item = sfc_flow_get_item(pattern->type);
840                 if (item == NULL) {
841                         rte_flow_error_set(error, ENOTSUP,
842                                            RTE_FLOW_ERROR_TYPE_ITEM, pattern,
843                                            "Unsupported pattern item");
844                         return -rte_errno;
845                 }
846
847                 /*
848                  * Omitting one or several protocol layers at the beginning
849                  * of pattern is supported
850                  */
851                 if (item->prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
852                     prev_layer != SFC_FLOW_ITEM_ANY_LAYER &&
853                     item->prev_layer != prev_layer) {
854                         rte_flow_error_set(error, ENOTSUP,
855                                            RTE_FLOW_ERROR_TYPE_ITEM, pattern,
856                                            "Unexpected sequence of pattern items");
857                         return -rte_errno;
858                 }
859
860                 rc = item->parse(pattern, &flow->spec, error);
861                 if (rc != 0)
862                         return rc;
863
864                 if (item->layer != SFC_FLOW_ITEM_ANY_LAYER)
865                         prev_layer = item->layer;
866         }
867
868         return 0;
869 }
870
871 static int
872 sfc_flow_parse_queue(struct sfc_adapter *sa,
873                      const struct rte_flow_action_queue *queue,
874                      struct rte_flow *flow)
875 {
876         struct sfc_rxq *rxq;
877
878         if (queue->index >= sa->rxq_count)
879                 return -EINVAL;
880
881         rxq = sa->rxq_info[queue->index].rxq;
882         flow->spec.efs_dmaq_id = (uint16_t)rxq->hw_index;
883
884         return 0;
885 }
886
887 #if EFSYS_OPT_RX_SCALE
888 static int
889 sfc_flow_parse_rss(struct sfc_adapter *sa,
890                    const struct rte_flow_action_rss *rss,
891                    struct rte_flow *flow)
892 {
893         unsigned int rxq_sw_index;
894         struct sfc_rxq *rxq;
895         unsigned int rxq_hw_index_min;
896         unsigned int rxq_hw_index_max;
897         const struct rte_eth_rss_conf *rss_conf = rss->rss_conf;
898         uint64_t rss_hf;
899         uint8_t *rss_key = NULL;
900         struct sfc_flow_rss *sfc_rss_conf = &flow->rss_conf;
901         unsigned int i;
902
903         if (rss->num == 0)
904                 return -EINVAL;
905
906         rxq_sw_index = sa->rxq_count - 1;
907         rxq = sa->rxq_info[rxq_sw_index].rxq;
908         rxq_hw_index_min = rxq->hw_index;
909         rxq_hw_index_max = 0;
910
911         for (i = 0; i < rss->num; ++i) {
912                 rxq_sw_index = rss->queue[i];
913
914                 if (rxq_sw_index >= sa->rxq_count)
915                         return -EINVAL;
916
917                 rxq = sa->rxq_info[rxq_sw_index].rxq;
918
919                 if (rxq->hw_index < rxq_hw_index_min)
920                         rxq_hw_index_min = rxq->hw_index;
921
922                 if (rxq->hw_index > rxq_hw_index_max)
923                         rxq_hw_index_max = rxq->hw_index;
924         }
925
926         rss_hf = (rss_conf != NULL) ? rss_conf->rss_hf : SFC_RSS_OFFLOADS;
927         if ((rss_hf & ~SFC_RSS_OFFLOADS) != 0)
928                 return -EINVAL;
929
930         if (rss_conf != NULL) {
931                 if (rss_conf->rss_key_len != sizeof(sa->rss_key))
932                         return -EINVAL;
933
934                 rss_key = rss_conf->rss_key;
935         } else {
936                 rss_key = sa->rss_key;
937         }
938
939         flow->rss = B_TRUE;
940
941         sfc_rss_conf->rxq_hw_index_min = rxq_hw_index_min;
942         sfc_rss_conf->rxq_hw_index_max = rxq_hw_index_max;
943         sfc_rss_conf->rss_hash_types = sfc_rte_to_efx_hash_type(rss_hf);
944         rte_memcpy(sfc_rss_conf->rss_key, rss_key, sizeof(sa->rss_key));
945
946         for (i = 0; i < RTE_DIM(sfc_rss_conf->rss_tbl); ++i) {
947                 unsigned int rxq_sw_index = rss->queue[i % rss->num];
948                 struct sfc_rxq *rxq = sa->rxq_info[rxq_sw_index].rxq;
949
950                 sfc_rss_conf->rss_tbl[i] = rxq->hw_index - rxq_hw_index_min;
951         }
952
953         return 0;
954 }
955 #endif /* EFSYS_OPT_RX_SCALE */
956
957 static int
958 sfc_flow_filter_insert(struct sfc_adapter *sa,
959                        struct rte_flow *flow)
960 {
961         efx_filter_spec_t *spec = &flow->spec;
962
963 #if EFSYS_OPT_RX_SCALE
964         struct sfc_flow_rss *rss = &flow->rss_conf;
965         int rc = 0;
966
967         if (flow->rss) {
968                 unsigned int rss_spread = MIN(rss->rxq_hw_index_max -
969                                               rss->rxq_hw_index_min + 1,
970                                               EFX_MAXRSS);
971
972                 rc = efx_rx_scale_context_alloc(sa->nic,
973                                                 EFX_RX_SCALE_EXCLUSIVE,
974                                                 rss_spread,
975                                                 &spec->efs_rss_context);
976                 if (rc != 0)
977                         goto fail_scale_context_alloc;
978
979                 rc = efx_rx_scale_mode_set(sa->nic, spec->efs_rss_context,
980                                            EFX_RX_HASHALG_TOEPLITZ,
981                                            rss->rss_hash_types, B_TRUE);
982                 if (rc != 0)
983                         goto fail_scale_mode_set;
984
985                 rc = efx_rx_scale_key_set(sa->nic, spec->efs_rss_context,
986                                           rss->rss_key,
987                                           sizeof(sa->rss_key));
988                 if (rc != 0)
989                         goto fail_scale_key_set;
990
991                 spec->efs_dmaq_id = rss->rxq_hw_index_min;
992                 spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS;
993         }
994
995         rc = efx_filter_insert(sa->nic, spec);
996         if (rc != 0)
997                 goto fail_filter_insert;
998
999         if (flow->rss) {
1000                 /*
1001                  * Scale table is set after filter insertion because
1002                  * the table entries are relative to the base RxQ ID
1003                  * and the latter is submitted to the HW by means of
1004                  * inserting a filter, so by the time of the request
1005                  * the HW knows all the information needed to verify
1006                  * the table entries, and the operation will succeed
1007                  */
1008                 rc = efx_rx_scale_tbl_set(sa->nic, spec->efs_rss_context,
1009                                           rss->rss_tbl, RTE_DIM(rss->rss_tbl));
1010                 if (rc != 0)
1011                         goto fail_scale_tbl_set;
1012         }
1013
1014         return 0;
1015
1016 fail_scale_tbl_set:
1017         efx_filter_remove(sa->nic, spec);
1018
1019 fail_filter_insert:
1020 fail_scale_key_set:
1021 fail_scale_mode_set:
1022         if (flow->rss)
1023                 efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
1024
1025 fail_scale_context_alloc:
1026         return rc;
1027 #else /* !EFSYS_OPT_RX_SCALE */
1028         return efx_filter_insert(sa->nic, spec);
1029 #endif /* EFSYS_OPT_RX_SCALE */
1030 }
1031
1032 static int
1033 sfc_flow_filter_remove(struct sfc_adapter *sa,
1034                        struct rte_flow *flow)
1035 {
1036         efx_filter_spec_t *spec = &flow->spec;
1037         int rc = 0;
1038
1039         rc = efx_filter_remove(sa->nic, spec);
1040         if (rc != 0)
1041                 return rc;
1042
1043 #if EFSYS_OPT_RX_SCALE
1044         if (flow->rss)
1045                 rc = efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
1046 #endif /* EFSYS_OPT_RX_SCALE */
1047
1048         return rc;
1049 }
1050
1051 static int
1052 sfc_flow_parse_actions(struct sfc_adapter *sa,
1053                        const struct rte_flow_action actions[],
1054                        struct rte_flow *flow,
1055                        struct rte_flow_error *error)
1056 {
1057         int rc;
1058         boolean_t is_specified = B_FALSE;
1059
1060         if (actions == NULL) {
1061                 rte_flow_error_set(error, EINVAL,
1062                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
1063                                    "NULL actions");
1064                 return -rte_errno;
1065         }
1066
1067         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1068                 switch (actions->type) {
1069                 case RTE_FLOW_ACTION_TYPE_VOID:
1070                         break;
1071
1072                 case RTE_FLOW_ACTION_TYPE_QUEUE:
1073                         rc = sfc_flow_parse_queue(sa, actions->conf, flow);
1074                         if (rc != 0) {
1075                                 rte_flow_error_set(error, EINVAL,
1076                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
1077                                         "Bad QUEUE action");
1078                                 return -rte_errno;
1079                         }
1080
1081                         is_specified = B_TRUE;
1082                         break;
1083
1084 #if EFSYS_OPT_RX_SCALE
1085                 case RTE_FLOW_ACTION_TYPE_RSS:
1086                         rc = sfc_flow_parse_rss(sa, actions->conf, flow);
1087                         if (rc != 0) {
1088                                 rte_flow_error_set(error, rc,
1089                                         RTE_FLOW_ERROR_TYPE_ACTION, actions,
1090                                         "Bad RSS action");
1091                                 return -rte_errno;
1092                         }
1093
1094                         is_specified = B_TRUE;
1095                         break;
1096 #endif /* EFSYS_OPT_RX_SCALE */
1097
1098                 default:
1099                         rte_flow_error_set(error, ENOTSUP,
1100                                            RTE_FLOW_ERROR_TYPE_ACTION, actions,
1101                                            "Action is not supported");
1102                         return -rte_errno;
1103                 }
1104         }
1105
1106         if (!is_specified) {
1107                 rte_flow_error_set(error, EINVAL,
1108                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM, actions,
1109                                    "Action is unspecified");
1110                 return -rte_errno;
1111         }
1112
1113         return 0;
1114 }
1115
1116 static int
1117 sfc_flow_parse(struct rte_eth_dev *dev,
1118                const struct rte_flow_attr *attr,
1119                const struct rte_flow_item pattern[],
1120                const struct rte_flow_action actions[],
1121                struct rte_flow *flow,
1122                struct rte_flow_error *error)
1123 {
1124         struct sfc_adapter *sa = dev->data->dev_private;
1125         int rc;
1126
1127         rc = sfc_flow_parse_attr(attr, flow, error);
1128         if (rc != 0)
1129                 goto fail_bad_value;
1130
1131         rc = sfc_flow_parse_pattern(pattern, flow, error);
1132         if (rc != 0)
1133                 goto fail_bad_value;
1134
1135         rc = sfc_flow_parse_actions(sa, actions, flow, error);
1136         if (rc != 0)
1137                 goto fail_bad_value;
1138
1139         if (!sfc_filter_is_match_supported(sa, flow->spec.efs_match_flags)) {
1140                 rte_flow_error_set(error, ENOTSUP,
1141                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1142                                    "Flow rule pattern is not supported");
1143                 return -rte_errno;
1144         }
1145
1146 fail_bad_value:
1147         return rc;
1148 }
1149
1150 static int
1151 sfc_flow_validate(struct rte_eth_dev *dev,
1152                   const struct rte_flow_attr *attr,
1153                   const struct rte_flow_item pattern[],
1154                   const struct rte_flow_action actions[],
1155                   struct rte_flow_error *error)
1156 {
1157         struct rte_flow flow;
1158
1159         memset(&flow, 0, sizeof(flow));
1160
1161         return sfc_flow_parse(dev, attr, pattern, actions, &flow, error);
1162 }
1163
1164 static struct rte_flow *
1165 sfc_flow_create(struct rte_eth_dev *dev,
1166                 const struct rte_flow_attr *attr,
1167                 const struct rte_flow_item pattern[],
1168                 const struct rte_flow_action actions[],
1169                 struct rte_flow_error *error)
1170 {
1171         struct sfc_adapter *sa = dev->data->dev_private;
1172         struct rte_flow *flow = NULL;
1173         int rc;
1174
1175         flow = rte_zmalloc("sfc_rte_flow", sizeof(*flow), 0);
1176         if (flow == NULL) {
1177                 rte_flow_error_set(error, ENOMEM,
1178                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1179                                    "Failed to allocate memory");
1180                 goto fail_no_mem;
1181         }
1182
1183         rc = sfc_flow_parse(dev, attr, pattern, actions, flow, error);
1184         if (rc != 0)
1185                 goto fail_bad_value;
1186
1187         TAILQ_INSERT_TAIL(&sa->filter.flow_list, flow, entries);
1188
1189         sfc_adapter_lock(sa);
1190
1191         if (sa->state == SFC_ADAPTER_STARTED) {
1192                 rc = sfc_flow_filter_insert(sa, flow);
1193                 if (rc != 0) {
1194                         rte_flow_error_set(error, rc,
1195                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1196                                 "Failed to insert filter");
1197                         goto fail_filter_insert;
1198                 }
1199         }
1200
1201         sfc_adapter_unlock(sa);
1202
1203         return flow;
1204
1205 fail_filter_insert:
1206         TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1207
1208 fail_bad_value:
1209         rte_free(flow);
1210         sfc_adapter_unlock(sa);
1211
1212 fail_no_mem:
1213         return NULL;
1214 }
1215
1216 static int
1217 sfc_flow_remove(struct sfc_adapter *sa,
1218                 struct rte_flow *flow,
1219                 struct rte_flow_error *error)
1220 {
1221         int rc = 0;
1222
1223         SFC_ASSERT(sfc_adapter_is_locked(sa));
1224
1225         if (sa->state == SFC_ADAPTER_STARTED) {
1226                 rc = sfc_flow_filter_remove(sa, flow);
1227                 if (rc != 0)
1228                         rte_flow_error_set(error, rc,
1229                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1230                                 "Failed to destroy flow rule");
1231         }
1232
1233         TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1234         rte_free(flow);
1235
1236         return rc;
1237 }
1238
1239 static int
1240 sfc_flow_destroy(struct rte_eth_dev *dev,
1241                  struct rte_flow *flow,
1242                  struct rte_flow_error *error)
1243 {
1244         struct sfc_adapter *sa = dev->data->dev_private;
1245         struct rte_flow *flow_ptr;
1246         int rc = EINVAL;
1247
1248         sfc_adapter_lock(sa);
1249
1250         TAILQ_FOREACH(flow_ptr, &sa->filter.flow_list, entries) {
1251                 if (flow_ptr == flow)
1252                         rc = 0;
1253         }
1254         if (rc != 0) {
1255                 rte_flow_error_set(error, rc,
1256                                    RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
1257                                    "Failed to find flow rule to destroy");
1258                 goto fail_bad_value;
1259         }
1260
1261         rc = sfc_flow_remove(sa, flow, error);
1262
1263 fail_bad_value:
1264         sfc_adapter_unlock(sa);
1265
1266         return -rc;
1267 }
1268
1269 static int
1270 sfc_flow_flush(struct rte_eth_dev *dev,
1271                struct rte_flow_error *error)
1272 {
1273         struct sfc_adapter *sa = dev->data->dev_private;
1274         struct rte_flow *flow;
1275         int rc = 0;
1276         int ret = 0;
1277
1278         sfc_adapter_lock(sa);
1279
1280         while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1281                 rc = sfc_flow_remove(sa, flow, error);
1282                 if (rc != 0)
1283                         ret = rc;
1284         }
1285
1286         sfc_adapter_unlock(sa);
1287
1288         return -ret;
1289 }
1290
1291 static int
1292 sfc_flow_isolate(struct rte_eth_dev *dev, int enable,
1293                  struct rte_flow_error *error)
1294 {
1295         struct sfc_adapter *sa = dev->data->dev_private;
1296         struct sfc_port *port = &sa->port;
1297         int ret = 0;
1298
1299         sfc_adapter_lock(sa);
1300         if (sa->state != SFC_ADAPTER_INITIALIZED) {
1301                 rte_flow_error_set(error, EBUSY,
1302                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1303                                    NULL, "please close the port first");
1304                 ret = -rte_errno;
1305         } else {
1306                 port->isolated = (enable) ? B_TRUE : B_FALSE;
1307         }
1308         sfc_adapter_unlock(sa);
1309
1310         return ret;
1311 }
1312
1313 const struct rte_flow_ops sfc_flow_ops = {
1314         .validate = sfc_flow_validate,
1315         .create = sfc_flow_create,
1316         .destroy = sfc_flow_destroy,
1317         .flush = sfc_flow_flush,
1318         .query = NULL,
1319         .isolate = sfc_flow_isolate,
1320 };
1321
1322 void
1323 sfc_flow_init(struct sfc_adapter *sa)
1324 {
1325         SFC_ASSERT(sfc_adapter_is_locked(sa));
1326
1327         TAILQ_INIT(&sa->filter.flow_list);
1328 }
1329
1330 void
1331 sfc_flow_fini(struct sfc_adapter *sa)
1332 {
1333         struct rte_flow *flow;
1334
1335         SFC_ASSERT(sfc_adapter_is_locked(sa));
1336
1337         while ((flow = TAILQ_FIRST(&sa->filter.flow_list)) != NULL) {
1338                 TAILQ_REMOVE(&sa->filter.flow_list, flow, entries);
1339                 rte_free(flow);
1340         }
1341 }
1342
1343 void
1344 sfc_flow_stop(struct sfc_adapter *sa)
1345 {
1346         struct rte_flow *flow;
1347
1348         SFC_ASSERT(sfc_adapter_is_locked(sa));
1349
1350         TAILQ_FOREACH(flow, &sa->filter.flow_list, entries)
1351                 sfc_flow_filter_remove(sa, flow);
1352 }
1353
1354 int
1355 sfc_flow_start(struct sfc_adapter *sa)
1356 {
1357         struct rte_flow *flow;
1358         int rc = 0;
1359
1360         sfc_log_init(sa, "entry");
1361
1362         SFC_ASSERT(sfc_adapter_is_locked(sa));
1363
1364         TAILQ_FOREACH(flow, &sa->filter.flow_list, entries) {
1365                 rc = sfc_flow_filter_insert(sa, flow);
1366                 if (rc != 0)
1367                         goto fail_bad_flow;
1368         }
1369
1370         sfc_log_init(sa, "done");
1371
1372 fail_bad_flow:
1373         return rc;
1374 }