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