net/enic: check for unsupported flow item types
[dpdk.git] / drivers / net / enic / enic_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2008-2017 Cisco Systems, Inc.  All rights reserved.
3  */
4
5 #include <errno.h>
6 #include <stdint.h>
7 #include <rte_log.h>
8 #include <rte_ethdev_driver.h>
9 #include <rte_flow_driver.h>
10 #include <rte_ether.h>
11 #include <rte_ip.h>
12 #include <rte_udp.h>
13
14 #include "enic_compat.h"
15 #include "enic.h"
16 #include "vnic_dev.h"
17 #include "vnic_nic.h"
18
19 #define FLOW_TRACE() \
20         rte_log(RTE_LOG_DEBUG, enicpmd_logtype_flow, \
21                 "%s()\n", __func__)
22 #define FLOW_LOG(level, fmt, args...) \
23         rte_log(RTE_LOG_ ## level, enicpmd_logtype_flow, \
24                 fmt "\n", ##args)
25
26 /** Info about how to copy items into enic filters. */
27 struct enic_items {
28         /** Function for copying and validating an item. */
29         int (*copy_item)(const struct rte_flow_item *item,
30                          struct filter_v2 *enic_filter, u8 *inner_ofst);
31         /** List of valid previous items. */
32         const enum rte_flow_item_type * const prev_items;
33         /** True if it's OK for this item to be the first item. For some NIC
34          * versions, it's invalid to start the stack above layer 3.
35          */
36         const u8 valid_start_item;
37 };
38
39 /** Filtering capabilities for various NIC and firmware versions. */
40 struct enic_filter_cap {
41         /** list of valid items and their handlers and attributes. */
42         const struct enic_items *item_info;
43         /* Max type in the above list, used to detect unsupported types */
44         enum rte_flow_item_type max_item_type;
45 };
46
47 /* functions for copying flow actions into enic actions */
48 typedef int (copy_action_fn)(const struct rte_flow_action actions[],
49                              struct filter_action_v2 *enic_action);
50
51 /* functions for copying items into enic filters */
52 typedef int(enic_copy_item_fn)(const struct rte_flow_item *item,
53                           struct filter_v2 *enic_filter, u8 *inner_ofst);
54
55 /** Action capabilities for various NICs. */
56 struct enic_action_cap {
57         /** list of valid actions */
58         const enum rte_flow_action_type *actions;
59         /** copy function for a particular NIC */
60         int (*copy_fn)(const struct rte_flow_action actions[],
61                        struct filter_action_v2 *enic_action);
62 };
63
64 /* Forward declarations */
65 static enic_copy_item_fn enic_copy_item_ipv4_v1;
66 static enic_copy_item_fn enic_copy_item_udp_v1;
67 static enic_copy_item_fn enic_copy_item_tcp_v1;
68 static enic_copy_item_fn enic_copy_item_eth_v2;
69 static enic_copy_item_fn enic_copy_item_vlan_v2;
70 static enic_copy_item_fn enic_copy_item_ipv4_v2;
71 static enic_copy_item_fn enic_copy_item_ipv6_v2;
72 static enic_copy_item_fn enic_copy_item_udp_v2;
73 static enic_copy_item_fn enic_copy_item_tcp_v2;
74 static enic_copy_item_fn enic_copy_item_sctp_v2;
75 static enic_copy_item_fn enic_copy_item_vxlan_v2;
76 static copy_action_fn enic_copy_action_v1;
77 static copy_action_fn enic_copy_action_v2;
78
79 /**
80  * Legacy NICs or NICs with outdated firmware. Only 5-tuple perfect match
81  * is supported.
82  */
83 static const struct enic_items enic_items_v1[] = {
84         [RTE_FLOW_ITEM_TYPE_IPV4] = {
85                 .copy_item = enic_copy_item_ipv4_v1,
86                 .valid_start_item = 1,
87                 .prev_items = (const enum rte_flow_item_type[]) {
88                                RTE_FLOW_ITEM_TYPE_END,
89                 },
90         },
91         [RTE_FLOW_ITEM_TYPE_UDP] = {
92                 .copy_item = enic_copy_item_udp_v1,
93                 .valid_start_item = 0,
94                 .prev_items = (const enum rte_flow_item_type[]) {
95                                RTE_FLOW_ITEM_TYPE_IPV4,
96                                RTE_FLOW_ITEM_TYPE_END,
97                 },
98         },
99         [RTE_FLOW_ITEM_TYPE_TCP] = {
100                 .copy_item = enic_copy_item_tcp_v1,
101                 .valid_start_item = 0,
102                 .prev_items = (const enum rte_flow_item_type[]) {
103                                RTE_FLOW_ITEM_TYPE_IPV4,
104                                RTE_FLOW_ITEM_TYPE_END,
105                 },
106         },
107 };
108
109 /**
110  * NICs have Advanced Filters capability but they are disabled. This means
111  * that layer 3 must be specified.
112  */
113 static const struct enic_items enic_items_v2[] = {
114         [RTE_FLOW_ITEM_TYPE_ETH] = {
115                 .copy_item = enic_copy_item_eth_v2,
116                 .valid_start_item = 1,
117                 .prev_items = (const enum rte_flow_item_type[]) {
118                                RTE_FLOW_ITEM_TYPE_VXLAN,
119                                RTE_FLOW_ITEM_TYPE_END,
120                 },
121         },
122         [RTE_FLOW_ITEM_TYPE_VLAN] = {
123                 .copy_item = enic_copy_item_vlan_v2,
124                 .valid_start_item = 1,
125                 .prev_items = (const enum rte_flow_item_type[]) {
126                                RTE_FLOW_ITEM_TYPE_ETH,
127                                RTE_FLOW_ITEM_TYPE_END,
128                 },
129         },
130         [RTE_FLOW_ITEM_TYPE_IPV4] = {
131                 .copy_item = enic_copy_item_ipv4_v2,
132                 .valid_start_item = 1,
133                 .prev_items = (const enum rte_flow_item_type[]) {
134                                RTE_FLOW_ITEM_TYPE_ETH,
135                                RTE_FLOW_ITEM_TYPE_VLAN,
136                                RTE_FLOW_ITEM_TYPE_END,
137                 },
138         },
139         [RTE_FLOW_ITEM_TYPE_IPV6] = {
140                 .copy_item = enic_copy_item_ipv6_v2,
141                 .valid_start_item = 1,
142                 .prev_items = (const enum rte_flow_item_type[]) {
143                                RTE_FLOW_ITEM_TYPE_ETH,
144                                RTE_FLOW_ITEM_TYPE_VLAN,
145                                RTE_FLOW_ITEM_TYPE_END,
146                 },
147         },
148         [RTE_FLOW_ITEM_TYPE_UDP] = {
149                 .copy_item = enic_copy_item_udp_v2,
150                 .valid_start_item = 0,
151                 .prev_items = (const enum rte_flow_item_type[]) {
152                                RTE_FLOW_ITEM_TYPE_IPV4,
153                                RTE_FLOW_ITEM_TYPE_IPV6,
154                                RTE_FLOW_ITEM_TYPE_END,
155                 },
156         },
157         [RTE_FLOW_ITEM_TYPE_TCP] = {
158                 .copy_item = enic_copy_item_tcp_v2,
159                 .valid_start_item = 0,
160                 .prev_items = (const enum rte_flow_item_type[]) {
161                                RTE_FLOW_ITEM_TYPE_IPV4,
162                                RTE_FLOW_ITEM_TYPE_IPV6,
163                                RTE_FLOW_ITEM_TYPE_END,
164                 },
165         },
166         [RTE_FLOW_ITEM_TYPE_SCTP] = {
167                 .copy_item = enic_copy_item_sctp_v2,
168                 .valid_start_item = 0,
169                 .prev_items = (const enum rte_flow_item_type[]) {
170                                RTE_FLOW_ITEM_TYPE_IPV4,
171                                RTE_FLOW_ITEM_TYPE_IPV6,
172                                RTE_FLOW_ITEM_TYPE_END,
173                 },
174         },
175         [RTE_FLOW_ITEM_TYPE_VXLAN] = {
176                 .copy_item = enic_copy_item_vxlan_v2,
177                 .valid_start_item = 0,
178                 .prev_items = (const enum rte_flow_item_type[]) {
179                                RTE_FLOW_ITEM_TYPE_UDP,
180                                RTE_FLOW_ITEM_TYPE_END,
181                 },
182         },
183 };
184
185 /** NICs with Advanced filters enabled */
186 static const struct enic_items enic_items_v3[] = {
187         [RTE_FLOW_ITEM_TYPE_ETH] = {
188                 .copy_item = enic_copy_item_eth_v2,
189                 .valid_start_item = 1,
190                 .prev_items = (const enum rte_flow_item_type[]) {
191                                RTE_FLOW_ITEM_TYPE_VXLAN,
192                                RTE_FLOW_ITEM_TYPE_END,
193                 },
194         },
195         [RTE_FLOW_ITEM_TYPE_VLAN] = {
196                 .copy_item = enic_copy_item_vlan_v2,
197                 .valid_start_item = 1,
198                 .prev_items = (const enum rte_flow_item_type[]) {
199                                RTE_FLOW_ITEM_TYPE_ETH,
200                                RTE_FLOW_ITEM_TYPE_END,
201                 },
202         },
203         [RTE_FLOW_ITEM_TYPE_IPV4] = {
204                 .copy_item = enic_copy_item_ipv4_v2,
205                 .valid_start_item = 1,
206                 .prev_items = (const enum rte_flow_item_type[]) {
207                                RTE_FLOW_ITEM_TYPE_ETH,
208                                RTE_FLOW_ITEM_TYPE_VLAN,
209                                RTE_FLOW_ITEM_TYPE_END,
210                 },
211         },
212         [RTE_FLOW_ITEM_TYPE_IPV6] = {
213                 .copy_item = enic_copy_item_ipv6_v2,
214                 .valid_start_item = 1,
215                 .prev_items = (const enum rte_flow_item_type[]) {
216                                RTE_FLOW_ITEM_TYPE_ETH,
217                                RTE_FLOW_ITEM_TYPE_VLAN,
218                                RTE_FLOW_ITEM_TYPE_END,
219                 },
220         },
221         [RTE_FLOW_ITEM_TYPE_UDP] = {
222                 .copy_item = enic_copy_item_udp_v2,
223                 .valid_start_item = 1,
224                 .prev_items = (const enum rte_flow_item_type[]) {
225                                RTE_FLOW_ITEM_TYPE_IPV4,
226                                RTE_FLOW_ITEM_TYPE_IPV6,
227                                RTE_FLOW_ITEM_TYPE_END,
228                 },
229         },
230         [RTE_FLOW_ITEM_TYPE_TCP] = {
231                 .copy_item = enic_copy_item_tcp_v2,
232                 .valid_start_item = 1,
233                 .prev_items = (const enum rte_flow_item_type[]) {
234                                RTE_FLOW_ITEM_TYPE_IPV4,
235                                RTE_FLOW_ITEM_TYPE_IPV6,
236                                RTE_FLOW_ITEM_TYPE_END,
237                 },
238         },
239         [RTE_FLOW_ITEM_TYPE_SCTP] = {
240                 .copy_item = enic_copy_item_sctp_v2,
241                 .valid_start_item = 0,
242                 .prev_items = (const enum rte_flow_item_type[]) {
243                                RTE_FLOW_ITEM_TYPE_IPV4,
244                                RTE_FLOW_ITEM_TYPE_IPV6,
245                                RTE_FLOW_ITEM_TYPE_END,
246                 },
247         },
248         [RTE_FLOW_ITEM_TYPE_VXLAN] = {
249                 .copy_item = enic_copy_item_vxlan_v2,
250                 .valid_start_item = 1,
251                 .prev_items = (const enum rte_flow_item_type[]) {
252                                RTE_FLOW_ITEM_TYPE_UDP,
253                                RTE_FLOW_ITEM_TYPE_END,
254                 },
255         },
256 };
257
258 /** Filtering capabilities indexed this NICs supported filter type. */
259 static const struct enic_filter_cap enic_filter_cap[] = {
260         [FILTER_IPV4_5TUPLE] = {
261                 .item_info = enic_items_v1,
262                 .max_item_type = RTE_FLOW_ITEM_TYPE_TCP,
263         },
264         [FILTER_USNIC_IP] = {
265                 .item_info = enic_items_v2,
266                 .max_item_type = RTE_FLOW_ITEM_TYPE_VXLAN,
267         },
268         [FILTER_DPDK_1] = {
269                 .item_info = enic_items_v3,
270                 .max_item_type = RTE_FLOW_ITEM_TYPE_VXLAN,
271         },
272 };
273
274 /** Supported actions for older NICs */
275 static const enum rte_flow_action_type enic_supported_actions_v1[] = {
276         RTE_FLOW_ACTION_TYPE_QUEUE,
277         RTE_FLOW_ACTION_TYPE_END,
278 };
279
280 /** Supported actions for newer NICs */
281 static const enum rte_flow_action_type enic_supported_actions_v2_id[] = {
282         RTE_FLOW_ACTION_TYPE_QUEUE,
283         RTE_FLOW_ACTION_TYPE_MARK,
284         RTE_FLOW_ACTION_TYPE_FLAG,
285         RTE_FLOW_ACTION_TYPE_END,
286 };
287
288 static const enum rte_flow_action_type enic_supported_actions_v2_drop[] = {
289         RTE_FLOW_ACTION_TYPE_QUEUE,
290         RTE_FLOW_ACTION_TYPE_MARK,
291         RTE_FLOW_ACTION_TYPE_FLAG,
292         RTE_FLOW_ACTION_TYPE_DROP,
293         RTE_FLOW_ACTION_TYPE_END,
294 };
295
296 static const enum rte_flow_action_type enic_supported_actions_v2_count[] = {
297         RTE_FLOW_ACTION_TYPE_QUEUE,
298         RTE_FLOW_ACTION_TYPE_MARK,
299         RTE_FLOW_ACTION_TYPE_FLAG,
300         RTE_FLOW_ACTION_TYPE_DROP,
301         RTE_FLOW_ACTION_TYPE_COUNT,
302         RTE_FLOW_ACTION_TYPE_END,
303 };
304
305 /** Action capabilities indexed by NIC version information */
306 static const struct enic_action_cap enic_action_cap[] = {
307         [FILTER_ACTION_RQ_STEERING_FLAG] = {
308                 .actions = enic_supported_actions_v1,
309                 .copy_fn = enic_copy_action_v1,
310         },
311         [FILTER_ACTION_FILTER_ID_FLAG] = {
312                 .actions = enic_supported_actions_v2_id,
313                 .copy_fn = enic_copy_action_v2,
314         },
315         [FILTER_ACTION_DROP_FLAG] = {
316                 .actions = enic_supported_actions_v2_drop,
317                 .copy_fn = enic_copy_action_v2,
318         },
319         [FILTER_ACTION_COUNTER_FLAG] = {
320                 .actions = enic_supported_actions_v2_count,
321                 .copy_fn = enic_copy_action_v2,
322         },
323 };
324
325 static int
326 mask_exact_match(const u8 *supported, const u8 *supplied,
327                  unsigned int size)
328 {
329         unsigned int i;
330         for (i = 0; i < size; i++) {
331                 if (supported[i] != supplied[i])
332                         return 0;
333         }
334         return 1;
335 }
336
337 /**
338  * Copy IPv4 item into version 1 NIC filter.
339  *
340  * @param item[in]
341  *   Item specification.
342  * @param enic_filter[out]
343  *   Partially filled in NIC filter structure.
344  * @param inner_ofst[in]
345  *   Should always be 0 for version 1.
346  */
347 static int
348 enic_copy_item_ipv4_v1(const struct rte_flow_item *item,
349                        struct filter_v2 *enic_filter, u8 *inner_ofst)
350 {
351         const struct rte_flow_item_ipv4 *spec = item->spec;
352         const struct rte_flow_item_ipv4 *mask = item->mask;
353         struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;
354         struct ipv4_hdr supported_mask = {
355                 .src_addr = 0xffffffff,
356                 .dst_addr = 0xffffffff,
357         };
358
359         FLOW_TRACE();
360
361         if (*inner_ofst)
362                 return ENOTSUP;
363
364         if (!mask)
365                 mask = &rte_flow_item_ipv4_mask;
366
367         /* This is an exact match filter, both fields must be set */
368         if (!spec || !spec->hdr.src_addr || !spec->hdr.dst_addr) {
369                 FLOW_LOG(ERR, "IPv4 exact match src/dst addr");
370                 return ENOTSUP;
371         }
372
373         /* check that the suppied mask exactly matches capabilty */
374         if (!mask_exact_match((const u8 *)&supported_mask,
375                               (const u8 *)item->mask, sizeof(*mask))) {
376                 FLOW_LOG(ERR, "IPv4 exact match mask");
377                 return ENOTSUP;
378         }
379
380         enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
381         enic_5tup->src_addr = spec->hdr.src_addr;
382         enic_5tup->dst_addr = spec->hdr.dst_addr;
383
384         return 0;
385 }
386
387 /**
388  * Copy UDP item into version 1 NIC filter.
389  *
390  * @param item[in]
391  *   Item specification.
392  * @param enic_filter[out]
393  *   Partially filled in NIC filter structure.
394  * @param inner_ofst[in]
395  *   Should always be 0 for version 1.
396  */
397 static int
398 enic_copy_item_udp_v1(const struct rte_flow_item *item,
399                       struct filter_v2 *enic_filter, u8 *inner_ofst)
400 {
401         const struct rte_flow_item_udp *spec = item->spec;
402         const struct rte_flow_item_udp *mask = item->mask;
403         struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;
404         struct udp_hdr supported_mask = {
405                 .src_port = 0xffff,
406                 .dst_port = 0xffff,
407         };
408
409         FLOW_TRACE();
410
411         if (*inner_ofst)
412                 return ENOTSUP;
413
414         if (!mask)
415                 mask = &rte_flow_item_udp_mask;
416
417         /* This is an exact match filter, both ports must be set */
418         if (!spec || !spec->hdr.src_port || !spec->hdr.dst_port) {
419                 FLOW_LOG(ERR, "UDP exact match src/dst addr");
420                 return ENOTSUP;
421         }
422
423         /* check that the suppied mask exactly matches capabilty */
424         if (!mask_exact_match((const u8 *)&supported_mask,
425                               (const u8 *)item->mask, sizeof(*mask))) {
426                 FLOW_LOG(ERR, "UDP exact match mask");
427                 return ENOTSUP;
428         }
429
430         enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
431         enic_5tup->src_port = spec->hdr.src_port;
432         enic_5tup->dst_port = spec->hdr.dst_port;
433         enic_5tup->protocol = PROTO_UDP;
434
435         return 0;
436 }
437
438 /**
439  * Copy TCP item into version 1 NIC filter.
440  *
441  * @param item[in]
442  *   Item specification.
443  * @param enic_filter[out]
444  *   Partially filled in NIC filter structure.
445  * @param inner_ofst[in]
446  *   Should always be 0 for version 1.
447  */
448 static int
449 enic_copy_item_tcp_v1(const struct rte_flow_item *item,
450                       struct filter_v2 *enic_filter, u8 *inner_ofst)
451 {
452         const struct rte_flow_item_tcp *spec = item->spec;
453         const struct rte_flow_item_tcp *mask = item->mask;
454         struct filter_ipv4_5tuple *enic_5tup = &enic_filter->u.ipv4;
455         struct tcp_hdr supported_mask = {
456                 .src_port = 0xffff,
457                 .dst_port = 0xffff,
458         };
459
460         FLOW_TRACE();
461
462         if (*inner_ofst)
463                 return ENOTSUP;
464
465         if (!mask)
466                 mask = &rte_flow_item_tcp_mask;
467
468         /* This is an exact match filter, both ports must be set */
469         if (!spec || !spec->hdr.src_port || !spec->hdr.dst_port) {
470                 FLOW_LOG(ERR, "TCPIPv4 exact match src/dst addr");
471                 return ENOTSUP;
472         }
473
474         /* check that the suppied mask exactly matches capabilty */
475         if (!mask_exact_match((const u8 *)&supported_mask,
476                              (const u8 *)item->mask, sizeof(*mask))) {
477                 FLOW_LOG(ERR, "TCP exact match mask");
478                 return ENOTSUP;
479         }
480
481         enic_filter->u.ipv4.flags = FILTER_FIELDS_IPV4_5TUPLE;
482         enic_5tup->src_port = spec->hdr.src_port;
483         enic_5tup->dst_port = spec->hdr.dst_port;
484         enic_5tup->protocol = PROTO_TCP;
485
486         return 0;
487 }
488
489 /**
490  * Copy ETH item into version 2 NIC filter.
491  *
492  * @param item[in]
493  *   Item specification.
494  * @param enic_filter[out]
495  *   Partially filled in NIC filter structure.
496  * @param inner_ofst[in]
497  *   If zero, this is an outer header. If non-zero, this is the offset into L5
498  *   where the header begins.
499  */
500 static int
501 enic_copy_item_eth_v2(const struct rte_flow_item *item,
502                       struct filter_v2 *enic_filter, u8 *inner_ofst)
503 {
504         struct ether_hdr enic_spec;
505         struct ether_hdr enic_mask;
506         const struct rte_flow_item_eth *spec = item->spec;
507         const struct rte_flow_item_eth *mask = item->mask;
508         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
509
510         FLOW_TRACE();
511
512         /* Match all if no spec */
513         if (!spec)
514                 return 0;
515
516         if (!mask)
517                 mask = &rte_flow_item_eth_mask;
518
519         memcpy(enic_spec.d_addr.addr_bytes, spec->dst.addr_bytes,
520                ETHER_ADDR_LEN);
521         memcpy(enic_spec.s_addr.addr_bytes, spec->src.addr_bytes,
522                ETHER_ADDR_LEN);
523
524         memcpy(enic_mask.d_addr.addr_bytes, mask->dst.addr_bytes,
525                ETHER_ADDR_LEN);
526         memcpy(enic_mask.s_addr.addr_bytes, mask->src.addr_bytes,
527                ETHER_ADDR_LEN);
528         enic_spec.ether_type = spec->type;
529         enic_mask.ether_type = mask->type;
530
531         if (*inner_ofst == 0) {
532                 /* outer header */
533                 memcpy(gp->layer[FILTER_GENERIC_1_L2].mask, &enic_mask,
534                        sizeof(struct ether_hdr));
535                 memcpy(gp->layer[FILTER_GENERIC_1_L2].val, &enic_spec,
536                        sizeof(struct ether_hdr));
537         } else {
538                 /* inner header */
539                 if ((*inner_ofst + sizeof(struct ether_hdr)) >
540                      FILTER_GENERIC_1_KEY_LEN)
541                         return ENOTSUP;
542                 /* Offset into L5 where inner Ethernet header goes */
543                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],
544                        &enic_mask, sizeof(struct ether_hdr));
545                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],
546                        &enic_spec, sizeof(struct ether_hdr));
547                 *inner_ofst += sizeof(struct ether_hdr);
548         }
549         return 0;
550 }
551
552 /**
553  * Copy VLAN item into version 2 NIC filter.
554  *
555  * @param item[in]
556  *   Item specification.
557  * @param enic_filter[out]
558  *   Partially filled in NIC filter structure.
559  * @param inner_ofst[in]
560  *   If zero, this is an outer header. If non-zero, this is the offset into L5
561  *   where the header begins.
562  */
563 static int
564 enic_copy_item_vlan_v2(const struct rte_flow_item *item,
565                        struct filter_v2 *enic_filter, u8 *inner_ofst)
566 {
567         const struct rte_flow_item_vlan *spec = item->spec;
568         const struct rte_flow_item_vlan *mask = item->mask;
569         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
570
571         FLOW_TRACE();
572
573         /* Match all if no spec */
574         if (!spec)
575                 return 0;
576
577         if (!mask)
578                 mask = &rte_flow_item_vlan_mask;
579
580         if (*inner_ofst == 0) {
581                 struct ether_hdr *eth_mask =
582                         (void *)gp->layer[FILTER_GENERIC_1_L2].mask;
583                 struct ether_hdr *eth_val =
584                         (void *)gp->layer[FILTER_GENERIC_1_L2].val;
585
586                 /* Outer TPID cannot be matched */
587                 if (eth_mask->ether_type)
588                         return ENOTSUP;
589                 eth_mask->ether_type = mask->inner_type;
590                 eth_val->ether_type = spec->inner_type;
591
592                 /* Outer header. Use the vlan mask/val fields */
593                 gp->mask_vlan = mask->tci;
594                 gp->val_vlan = spec->tci;
595         } else {
596                 /* Inner header. Mask/Val start at *inner_ofst into L5 */
597                 if ((*inner_ofst + sizeof(struct vlan_hdr)) >
598                      FILTER_GENERIC_1_KEY_LEN)
599                         return ENOTSUP;
600                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],
601                        mask, sizeof(struct vlan_hdr));
602                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],
603                        spec, sizeof(struct vlan_hdr));
604                 *inner_ofst += sizeof(struct vlan_hdr);
605         }
606         return 0;
607 }
608
609 /**
610  * Copy IPv4 item into version 2 NIC filter.
611  *
612  * @param item[in]
613  *   Item specification.
614  * @param enic_filter[out]
615  *   Partially filled in NIC filter structure.
616  * @param inner_ofst[in]
617  *   Must be 0. Don't support inner IPv4 filtering.
618  */
619 static int
620 enic_copy_item_ipv4_v2(const struct rte_flow_item *item,
621                        struct filter_v2 *enic_filter, u8 *inner_ofst)
622 {
623         const struct rte_flow_item_ipv4 *spec = item->spec;
624         const struct rte_flow_item_ipv4 *mask = item->mask;
625         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
626
627         FLOW_TRACE();
628
629         if (*inner_ofst == 0) {
630                 /* Match IPv4 */
631                 gp->mask_flags |= FILTER_GENERIC_1_IPV4;
632                 gp->val_flags |= FILTER_GENERIC_1_IPV4;
633
634                 /* Match all if no spec */
635                 if (!spec)
636                         return 0;
637
638                 if (!mask)
639                         mask = &rte_flow_item_ipv4_mask;
640
641                 memcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr,
642                        sizeof(struct ipv4_hdr));
643                 memcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr,
644                        sizeof(struct ipv4_hdr));
645         } else {
646                 /* Inner IPv4 header. Mask/Val start at *inner_ofst into L5 */
647                 if ((*inner_ofst + sizeof(struct ipv4_hdr)) >
648                      FILTER_GENERIC_1_KEY_LEN)
649                         return ENOTSUP;
650                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],
651                        mask, sizeof(struct ipv4_hdr));
652                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],
653                        spec, sizeof(struct ipv4_hdr));
654                 *inner_ofst += sizeof(struct ipv4_hdr);
655         }
656         return 0;
657 }
658
659 /**
660  * Copy IPv6 item into version 2 NIC filter.
661  *
662  * @param item[in]
663  *   Item specification.
664  * @param enic_filter[out]
665  *   Partially filled in NIC filter structure.
666  * @param inner_ofst[in]
667  *   Must be 0. Don't support inner IPv6 filtering.
668  */
669 static int
670 enic_copy_item_ipv6_v2(const struct rte_flow_item *item,
671                        struct filter_v2 *enic_filter, u8 *inner_ofst)
672 {
673         const struct rte_flow_item_ipv6 *spec = item->spec;
674         const struct rte_flow_item_ipv6 *mask = item->mask;
675         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
676
677         FLOW_TRACE();
678
679         /* Match IPv6 */
680         gp->mask_flags |= FILTER_GENERIC_1_IPV6;
681         gp->val_flags |= FILTER_GENERIC_1_IPV6;
682
683         /* Match all if no spec */
684         if (!spec)
685                 return 0;
686
687         if (!mask)
688                 mask = &rte_flow_item_ipv6_mask;
689
690         if (*inner_ofst == 0) {
691                 memcpy(gp->layer[FILTER_GENERIC_1_L3].mask, &mask->hdr,
692                        sizeof(struct ipv6_hdr));
693                 memcpy(gp->layer[FILTER_GENERIC_1_L3].val, &spec->hdr,
694                        sizeof(struct ipv6_hdr));
695         } else {
696                 /* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */
697                 if ((*inner_ofst + sizeof(struct ipv6_hdr)) >
698                      FILTER_GENERIC_1_KEY_LEN)
699                         return ENOTSUP;
700                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],
701                        mask, sizeof(struct ipv6_hdr));
702                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],
703                        spec, sizeof(struct ipv6_hdr));
704                 *inner_ofst += sizeof(struct ipv6_hdr);
705         }
706         return 0;
707 }
708
709 /**
710  * Copy UDP item into version 2 NIC filter.
711  *
712  * @param item[in]
713  *   Item specification.
714  * @param enic_filter[out]
715  *   Partially filled in NIC filter structure.
716  * @param inner_ofst[in]
717  *   Must be 0. Don't support inner UDP filtering.
718  */
719 static int
720 enic_copy_item_udp_v2(const struct rte_flow_item *item,
721                       struct filter_v2 *enic_filter, u8 *inner_ofst)
722 {
723         const struct rte_flow_item_udp *spec = item->spec;
724         const struct rte_flow_item_udp *mask = item->mask;
725         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
726
727         FLOW_TRACE();
728
729         /* Match UDP */
730         gp->mask_flags |= FILTER_GENERIC_1_UDP;
731         gp->val_flags |= FILTER_GENERIC_1_UDP;
732
733         /* Match all if no spec */
734         if (!spec)
735                 return 0;
736
737         if (!mask)
738                 mask = &rte_flow_item_udp_mask;
739
740         if (*inner_ofst == 0) {
741                 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,
742                        sizeof(struct udp_hdr));
743                 memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,
744                        sizeof(struct udp_hdr));
745         } else {
746                 /* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */
747                 if ((*inner_ofst + sizeof(struct udp_hdr)) >
748                      FILTER_GENERIC_1_KEY_LEN)
749                         return ENOTSUP;
750                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],
751                        mask, sizeof(struct udp_hdr));
752                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],
753                        spec, sizeof(struct udp_hdr));
754                 *inner_ofst += sizeof(struct udp_hdr);
755         }
756         return 0;
757 }
758
759 /**
760  * Copy TCP item into version 2 NIC filter.
761  *
762  * @param item[in]
763  *   Item specification.
764  * @param enic_filter[out]
765  *   Partially filled in NIC filter structure.
766  * @param inner_ofst[in]
767  *   Must be 0. Don't support inner TCP filtering.
768  */
769 static int
770 enic_copy_item_tcp_v2(const struct rte_flow_item *item,
771                       struct filter_v2 *enic_filter, u8 *inner_ofst)
772 {
773         const struct rte_flow_item_tcp *spec = item->spec;
774         const struct rte_flow_item_tcp *mask = item->mask;
775         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
776
777         FLOW_TRACE();
778
779         /* Match TCP */
780         gp->mask_flags |= FILTER_GENERIC_1_TCP;
781         gp->val_flags |= FILTER_GENERIC_1_TCP;
782
783         /* Match all if no spec */
784         if (!spec)
785                 return 0;
786
787         if (!mask)
788                 return ENOTSUP;
789
790         if (*inner_ofst == 0) {
791                 memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,
792                        sizeof(struct tcp_hdr));
793                 memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,
794                        sizeof(struct tcp_hdr));
795         } else {
796                 /* Inner IPv6 header. Mask/Val start at *inner_ofst into L5 */
797                 if ((*inner_ofst + sizeof(struct tcp_hdr)) >
798                      FILTER_GENERIC_1_KEY_LEN)
799                         return ENOTSUP;
800                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].mask[*inner_ofst],
801                        mask, sizeof(struct tcp_hdr));
802                 memcpy(&gp->layer[FILTER_GENERIC_1_L5].val[*inner_ofst],
803                        spec, sizeof(struct tcp_hdr));
804                 *inner_ofst += sizeof(struct tcp_hdr);
805         }
806         return 0;
807 }
808
809 /**
810  * Copy SCTP item into version 2 NIC filter.
811  *
812  * @param item[in]
813  *   Item specification.
814  * @param enic_filter[out]
815  *   Partially filled in NIC filter structure.
816  * @param inner_ofst[in]
817  *   Must be 0. Don't support inner SCTP filtering.
818  */
819 static int
820 enic_copy_item_sctp_v2(const struct rte_flow_item *item,
821                        struct filter_v2 *enic_filter, u8 *inner_ofst)
822 {
823         const struct rte_flow_item_sctp *spec = item->spec;
824         const struct rte_flow_item_sctp *mask = item->mask;
825         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
826         uint8_t *ip_proto_mask = NULL;
827         uint8_t *ip_proto = NULL;
828
829         FLOW_TRACE();
830
831         if (*inner_ofst)
832                 return ENOTSUP;
833
834         /*
835          * The NIC filter API has no flags for "match sctp", so explicitly set
836          * the protocol number in the IP pattern.
837          */
838         if (gp->val_flags & FILTER_GENERIC_1_IPV4) {
839                 struct ipv4_hdr *ip;
840                 ip = (struct ipv4_hdr *)gp->layer[FILTER_GENERIC_1_L3].mask;
841                 ip_proto_mask = &ip->next_proto_id;
842                 ip = (struct ipv4_hdr *)gp->layer[FILTER_GENERIC_1_L3].val;
843                 ip_proto = &ip->next_proto_id;
844         } else if (gp->val_flags & FILTER_GENERIC_1_IPV6) {
845                 struct ipv6_hdr *ip;
846                 ip = (struct ipv6_hdr *)gp->layer[FILTER_GENERIC_1_L3].mask;
847                 ip_proto_mask = &ip->proto;
848                 ip = (struct ipv6_hdr *)gp->layer[FILTER_GENERIC_1_L3].val;
849                 ip_proto = &ip->proto;
850         } else {
851                 /* Need IPv4/IPv6 pattern first */
852                 return EINVAL;
853         }
854         *ip_proto = IPPROTO_SCTP;
855         *ip_proto_mask = 0xff;
856
857         /* Match all if no spec */
858         if (!spec)
859                 return 0;
860
861         if (!mask)
862                 mask = &rte_flow_item_sctp_mask;
863
864         memcpy(gp->layer[FILTER_GENERIC_1_L4].mask, &mask->hdr,
865                sizeof(struct sctp_hdr));
866         memcpy(gp->layer[FILTER_GENERIC_1_L4].val, &spec->hdr,
867                sizeof(struct sctp_hdr));
868         return 0;
869 }
870
871 /**
872  * Copy UDP item into version 2 NIC filter.
873  *
874  * @param item[in]
875  *   Item specification.
876  * @param enic_filter[out]
877  *   Partially filled in NIC filter structure.
878  * @param inner_ofst[in]
879  *   Must be 0. VxLAN headers always start at the beginning of L5.
880  */
881 static int
882 enic_copy_item_vxlan_v2(const struct rte_flow_item *item,
883                         struct filter_v2 *enic_filter, u8 *inner_ofst)
884 {
885         const struct rte_flow_item_vxlan *spec = item->spec;
886         const struct rte_flow_item_vxlan *mask = item->mask;
887         struct filter_generic_1 *gp = &enic_filter->u.generic_1;
888
889         FLOW_TRACE();
890
891         if (*inner_ofst)
892                 return EINVAL;
893
894         /* Match all if no spec */
895         if (!spec)
896                 return 0;
897
898         if (!mask)
899                 mask = &rte_flow_item_vxlan_mask;
900
901         memcpy(gp->layer[FILTER_GENERIC_1_L5].mask, mask,
902                sizeof(struct vxlan_hdr));
903         memcpy(gp->layer[FILTER_GENERIC_1_L5].val, spec,
904                sizeof(struct vxlan_hdr));
905
906         *inner_ofst = sizeof(struct vxlan_hdr);
907         return 0;
908 }
909
910 /**
911  * Return 1 if current item is valid on top of the previous one.
912  *
913  * @param prev_item[in]
914  *   The item before this one in the pattern or RTE_FLOW_ITEM_TYPE_END if this
915  *   is the first item.
916  * @param item_info[in]
917  *   Info about this item, like valid previous items.
918  * @param is_first[in]
919  *   True if this the first item in the pattern.
920  */
921 static int
922 item_stacking_valid(enum rte_flow_item_type prev_item,
923                     const struct enic_items *item_info, u8 is_first_item)
924 {
925         enum rte_flow_item_type const *allowed_items = item_info->prev_items;
926
927         FLOW_TRACE();
928
929         for (; *allowed_items != RTE_FLOW_ITEM_TYPE_END; allowed_items++) {
930                 if (prev_item == *allowed_items)
931                         return 1;
932         }
933
934         /* This is the first item in the stack. Check if that's cool */
935         if (is_first_item && item_info->valid_start_item)
936                 return 1;
937
938         return 0;
939 }
940
941 /**
942  * Build the intenal enic filter structure from the provided pattern. The
943  * pattern is validated as the items are copied.
944  *
945  * @param pattern[in]
946  * @param items_info[in]
947  *   Info about this NICs item support, like valid previous items.
948  * @param enic_filter[out]
949  *   NIC specfilc filters derived from the pattern.
950  * @param error[out]
951  */
952 static int
953 enic_copy_filter(const struct rte_flow_item pattern[],
954                  const struct enic_filter_cap *cap,
955                  struct filter_v2 *enic_filter,
956                  struct rte_flow_error *error)
957 {
958         int ret;
959         const struct rte_flow_item *item = pattern;
960         u8 inner_ofst = 0; /* If encapsulated, ofst into L5 */
961         enum rte_flow_item_type prev_item;
962         const struct enic_items *item_info;
963
964         u8 is_first_item = 1;
965
966         FLOW_TRACE();
967
968         prev_item = 0;
969
970         for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
971                 /* Get info about how to validate and copy the item. If NULL
972                  * is returned the nic does not support the item.
973                  */
974                 if (item->type == RTE_FLOW_ITEM_TYPE_VOID)
975                         continue;
976
977                 item_info = &cap->item_info[item->type];
978                 if (item->type > cap->max_item_type ||
979                     item_info->copy_item == NULL) {
980                         rte_flow_error_set(error, ENOTSUP,
981                                 RTE_FLOW_ERROR_TYPE_ITEM,
982                                 NULL, "Unsupported item.");
983                         return -rte_errno;
984                 }
985
986                 /* check to see if item stacking is valid */
987                 if (!item_stacking_valid(prev_item, item_info, is_first_item))
988                         goto stacking_error;
989
990                 ret = item_info->copy_item(item, enic_filter, &inner_ofst);
991                 if (ret)
992                         goto item_not_supported;
993                 prev_item = item->type;
994                 is_first_item = 0;
995         }
996         return 0;
997
998 item_not_supported:
999         rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_ITEM,
1000                            NULL, "enic type error");
1001         return -rte_errno;
1002
1003 stacking_error:
1004         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1005                            item, "stacking error");
1006         return -rte_errno;
1007 }
1008
1009 /**
1010  * Build the intenal version 1 NIC action structure from the provided pattern.
1011  * The pattern is validated as the items are copied.
1012  *
1013  * @param actions[in]
1014  * @param enic_action[out]
1015  *   NIC specfilc actions derived from the actions.
1016  * @param error[out]
1017  */
1018 static int
1019 enic_copy_action_v1(const struct rte_flow_action actions[],
1020                     struct filter_action_v2 *enic_action)
1021 {
1022         enum { FATE = 1, };
1023         uint32_t overlap = 0;
1024
1025         FLOW_TRACE();
1026
1027         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1028                 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID)
1029                         continue;
1030
1031                 switch (actions->type) {
1032                 case RTE_FLOW_ACTION_TYPE_QUEUE: {
1033                         const struct rte_flow_action_queue *queue =
1034                                 (const struct rte_flow_action_queue *)
1035                                 actions->conf;
1036
1037                         if (overlap & FATE)
1038                                 return ENOTSUP;
1039                         overlap |= FATE;
1040                         enic_action->rq_idx =
1041                                 enic_rte_rq_idx_to_sop_idx(queue->index);
1042                         break;
1043                 }
1044                 default:
1045                         RTE_ASSERT(0);
1046                         break;
1047                 }
1048         }
1049         if (!(overlap & FATE))
1050                 return ENOTSUP;
1051         enic_action->type = FILTER_ACTION_RQ_STEERING;
1052         return 0;
1053 }
1054
1055 /**
1056  * Build the intenal version 2 NIC action structure from the provided pattern.
1057  * The pattern is validated as the items are copied.
1058  *
1059  * @param actions[in]
1060  * @param enic_action[out]
1061  *   NIC specfilc actions derived from the actions.
1062  * @param error[out]
1063  */
1064 static int
1065 enic_copy_action_v2(const struct rte_flow_action actions[],
1066                     struct filter_action_v2 *enic_action)
1067 {
1068         enum { FATE = 1, MARK = 2, };
1069         uint32_t overlap = 0;
1070
1071         FLOW_TRACE();
1072
1073         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1074                 switch (actions->type) {
1075                 case RTE_FLOW_ACTION_TYPE_QUEUE: {
1076                         const struct rte_flow_action_queue *queue =
1077                                 (const struct rte_flow_action_queue *)
1078                                 actions->conf;
1079
1080                         if (overlap & FATE)
1081                                 return ENOTSUP;
1082                         overlap |= FATE;
1083                         enic_action->rq_idx =
1084                                 enic_rte_rq_idx_to_sop_idx(queue->index);
1085                         enic_action->flags |= FILTER_ACTION_RQ_STEERING_FLAG;
1086                         break;
1087                 }
1088                 case RTE_FLOW_ACTION_TYPE_MARK: {
1089                         const struct rte_flow_action_mark *mark =
1090                                 (const struct rte_flow_action_mark *)
1091                                 actions->conf;
1092
1093                         if (overlap & MARK)
1094                                 return ENOTSUP;
1095                         overlap |= MARK;
1096                         /*
1097                          * Map mark ID (32-bit) to filter ID (16-bit):
1098                          * - Reject values > 16 bits
1099                          * - Filter ID 0 is reserved for filters that steer
1100                          *   but not mark. So add 1 to the mark ID to avoid
1101                          *   using 0.
1102                          * - Filter ID (ENIC_MAGIC_FILTER_ID = 0xffff) is
1103                          *   reserved for the "flag" action below.
1104                          */
1105                         if (mark->id >= ENIC_MAGIC_FILTER_ID - 1)
1106                                 return EINVAL;
1107                         enic_action->filter_id = mark->id + 1;
1108                         enic_action->flags |= FILTER_ACTION_FILTER_ID_FLAG;
1109                         break;
1110                 }
1111                 case RTE_FLOW_ACTION_TYPE_FLAG: {
1112                         if (overlap & MARK)
1113                                 return ENOTSUP;
1114                         overlap |= MARK;
1115                         /* ENIC_MAGIC_FILTER_ID is reserved for flagging */
1116                         enic_action->filter_id = ENIC_MAGIC_FILTER_ID;
1117                         enic_action->flags |= FILTER_ACTION_FILTER_ID_FLAG;
1118                         break;
1119                 }
1120                 case RTE_FLOW_ACTION_TYPE_DROP: {
1121                         if (overlap & FATE)
1122                                 return ENOTSUP;
1123                         overlap |= FATE;
1124                         enic_action->flags |= FILTER_ACTION_DROP_FLAG;
1125                         break;
1126                 }
1127                 case RTE_FLOW_ACTION_TYPE_COUNT: {
1128                         enic_action->flags |= FILTER_ACTION_COUNTER_FLAG;
1129                         break;
1130                 }
1131                 case RTE_FLOW_ACTION_TYPE_VOID:
1132                         continue;
1133                 default:
1134                         RTE_ASSERT(0);
1135                         break;
1136                 }
1137         }
1138         if (!(overlap & FATE))
1139                 return ENOTSUP;
1140         enic_action->type = FILTER_ACTION_V2;
1141         return 0;
1142 }
1143
1144 /** Check if the action is supported */
1145 static int
1146 enic_match_action(const struct rte_flow_action *action,
1147                   const enum rte_flow_action_type *supported_actions)
1148 {
1149         for (; *supported_actions != RTE_FLOW_ACTION_TYPE_END;
1150              supported_actions++) {
1151                 if (action->type == *supported_actions)
1152                         return 1;
1153         }
1154         return 0;
1155 }
1156
1157 /** Get the NIC filter capabilties structure */
1158 static const struct enic_filter_cap *
1159 enic_get_filter_cap(struct enic *enic)
1160 {
1161         if (enic->flow_filter_mode)
1162                 return &enic_filter_cap[enic->flow_filter_mode];
1163
1164         return NULL;
1165 }
1166
1167 /** Get the actions for this NIC version. */
1168 static const struct enic_action_cap *
1169 enic_get_action_cap(struct enic *enic)
1170 {
1171         const struct enic_action_cap *ea;
1172         uint8_t actions;
1173
1174         actions = enic->filter_actions;
1175         if (actions & FILTER_ACTION_COUNTER_FLAG)
1176                 ea = &enic_action_cap[FILTER_ACTION_COUNTER_FLAG];
1177         else if (actions & FILTER_ACTION_DROP_FLAG)
1178                 ea = &enic_action_cap[FILTER_ACTION_DROP_FLAG];
1179         else if (actions & FILTER_ACTION_FILTER_ID_FLAG)
1180                 ea = &enic_action_cap[FILTER_ACTION_FILTER_ID_FLAG];
1181         else
1182                 ea = &enic_action_cap[FILTER_ACTION_RQ_STEERING_FLAG];
1183         return ea;
1184 }
1185
1186 /* Debug function to dump internal NIC action structure. */
1187 static void
1188 enic_dump_actions(const struct filter_action_v2 *ea)
1189 {
1190         if (ea->type == FILTER_ACTION_RQ_STEERING) {
1191                 FLOW_LOG(INFO, "Action(V1), queue: %u\n", ea->rq_idx);
1192         } else if (ea->type == FILTER_ACTION_V2) {
1193                 FLOW_LOG(INFO, "Actions(V2)\n");
1194                 if (ea->flags & FILTER_ACTION_RQ_STEERING_FLAG)
1195                         FLOW_LOG(INFO, "\tqueue: %u\n",
1196                                enic_sop_rq_idx_to_rte_idx(ea->rq_idx));
1197                 if (ea->flags & FILTER_ACTION_FILTER_ID_FLAG)
1198                         FLOW_LOG(INFO, "\tfilter_id: %u\n", ea->filter_id);
1199         }
1200 }
1201
1202 /* Debug function to dump internal NIC filter structure. */
1203 static void
1204 enic_dump_filter(const struct filter_v2 *filt)
1205 {
1206         const struct filter_generic_1 *gp;
1207         int i, j, mbyte;
1208         char buf[128], *bp;
1209         char ip4[16], ip6[16], udp[16], tcp[16], tcpudp[16], ip4csum[16];
1210         char l4csum[16], ipfrag[16];
1211
1212         switch (filt->type) {
1213         case FILTER_IPV4_5TUPLE:
1214                 FLOW_LOG(INFO, "FILTER_IPV4_5TUPLE\n");
1215                 break;
1216         case FILTER_USNIC_IP:
1217         case FILTER_DPDK_1:
1218                 /* FIXME: this should be a loop */
1219                 gp = &filt->u.generic_1;
1220                 FLOW_LOG(INFO, "Filter: vlan: 0x%04x, mask: 0x%04x\n",
1221                        gp->val_vlan, gp->mask_vlan);
1222
1223                 if (gp->mask_flags & FILTER_GENERIC_1_IPV4)
1224                         sprintf(ip4, "%s ",
1225                                 (gp->val_flags & FILTER_GENERIC_1_IPV4)
1226                                  ? "ip4(y)" : "ip4(n)");
1227                 else
1228                         sprintf(ip4, "%s ", "ip4(x)");
1229
1230                 if (gp->mask_flags & FILTER_GENERIC_1_IPV6)
1231                         sprintf(ip6, "%s ",
1232                                 (gp->val_flags & FILTER_GENERIC_1_IPV4)
1233                                  ? "ip6(y)" : "ip6(n)");
1234                 else
1235                         sprintf(ip6, "%s ", "ip6(x)");
1236
1237                 if (gp->mask_flags & FILTER_GENERIC_1_UDP)
1238                         sprintf(udp, "%s ",
1239                                 (gp->val_flags & FILTER_GENERIC_1_UDP)
1240                                  ? "udp(y)" : "udp(n)");
1241                 else
1242                         sprintf(udp, "%s ", "udp(x)");
1243
1244                 if (gp->mask_flags & FILTER_GENERIC_1_TCP)
1245                         sprintf(tcp, "%s ",
1246                                 (gp->val_flags & FILTER_GENERIC_1_TCP)
1247                                  ? "tcp(y)" : "tcp(n)");
1248                 else
1249                         sprintf(tcp, "%s ", "tcp(x)");
1250
1251                 if (gp->mask_flags & FILTER_GENERIC_1_TCP_OR_UDP)
1252                         sprintf(tcpudp, "%s ",
1253                                 (gp->val_flags & FILTER_GENERIC_1_TCP_OR_UDP)
1254                                  ? "tcpudp(y)" : "tcpudp(n)");
1255                 else
1256                         sprintf(tcpudp, "%s ", "tcpudp(x)");
1257
1258                 if (gp->mask_flags & FILTER_GENERIC_1_IP4SUM_OK)
1259                         sprintf(ip4csum, "%s ",
1260                                 (gp->val_flags & FILTER_GENERIC_1_IP4SUM_OK)
1261                                  ? "ip4csum(y)" : "ip4csum(n)");
1262                 else
1263                         sprintf(ip4csum, "%s ", "ip4csum(x)");
1264
1265                 if (gp->mask_flags & FILTER_GENERIC_1_L4SUM_OK)
1266                         sprintf(l4csum, "%s ",
1267                                 (gp->val_flags & FILTER_GENERIC_1_L4SUM_OK)
1268                                  ? "l4csum(y)" : "l4csum(n)");
1269                 else
1270                         sprintf(l4csum, "%s ", "l4csum(x)");
1271
1272                 if (gp->mask_flags & FILTER_GENERIC_1_IPFRAG)
1273                         sprintf(ipfrag, "%s ",
1274                                 (gp->val_flags & FILTER_GENERIC_1_IPFRAG)
1275                                  ? "ipfrag(y)" : "ipfrag(n)");
1276                 else
1277                         sprintf(ipfrag, "%s ", "ipfrag(x)");
1278                 FLOW_LOG(INFO, "\tFlags: %s%s%s%s%s%s%s%s\n", ip4, ip6, udp,
1279                          tcp, tcpudp, ip4csum, l4csum, ipfrag);
1280
1281                 for (i = 0; i < FILTER_GENERIC_1_NUM_LAYERS; i++) {
1282                         mbyte = FILTER_GENERIC_1_KEY_LEN - 1;
1283                         while (mbyte && !gp->layer[i].mask[mbyte])
1284                                 mbyte--;
1285                         if (mbyte == 0)
1286                                 continue;
1287
1288                         bp = buf;
1289                         for (j = 0; j <= mbyte; j++) {
1290                                 sprintf(bp, "%02x",
1291                                         gp->layer[i].mask[j]);
1292                                 bp += 2;
1293                         }
1294                         *bp = '\0';
1295                         FLOW_LOG(INFO, "\tL%u mask: %s\n", i + 2, buf);
1296                         bp = buf;
1297                         for (j = 0; j <= mbyte; j++) {
1298                                 sprintf(bp, "%02x",
1299                                         gp->layer[i].val[j]);
1300                                 bp += 2;
1301                         }
1302                         *bp = '\0';
1303                         FLOW_LOG(INFO, "\tL%u  val: %s\n", i + 2, buf);
1304                 }
1305                 break;
1306         default:
1307                 FLOW_LOG(INFO, "FILTER UNKNOWN\n");
1308                 break;
1309         }
1310 }
1311
1312 /* Debug function to dump internal NIC flow structures. */
1313 static void
1314 enic_dump_flow(const struct filter_action_v2 *ea, const struct filter_v2 *filt)
1315 {
1316         enic_dump_filter(filt);
1317         enic_dump_actions(ea);
1318 }
1319
1320
1321 /**
1322  * Internal flow parse/validate function.
1323  *
1324  * @param dev[in]
1325  *   This device pointer.
1326  * @param pattern[in]
1327  * @param actions[in]
1328  * @param error[out]
1329  * @param enic_filter[out]
1330  *   Internal NIC filter structure pointer.
1331  * @param enic_action[out]
1332  *   Internal NIC action structure pointer.
1333  */
1334 static int
1335 enic_flow_parse(struct rte_eth_dev *dev,
1336                 const struct rte_flow_attr *attrs,
1337                 const struct rte_flow_item pattern[],
1338                 const struct rte_flow_action actions[],
1339                 struct rte_flow_error *error,
1340                 struct filter_v2 *enic_filter,
1341                 struct filter_action_v2 *enic_action)
1342 {
1343         unsigned int ret = 0;
1344         struct enic *enic = pmd_priv(dev);
1345         const struct enic_filter_cap *enic_filter_cap;
1346         const struct enic_action_cap *enic_action_cap;
1347         const struct rte_flow_action *action;
1348
1349         FLOW_TRACE();
1350
1351         memset(enic_filter, 0, sizeof(*enic_filter));
1352         memset(enic_action, 0, sizeof(*enic_action));
1353
1354         if (!pattern) {
1355                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
1356                                    NULL, "No pattern specified");
1357                 return -rte_errno;
1358         }
1359
1360         if (!actions) {
1361                 rte_flow_error_set(error, EINVAL,
1362                                    RTE_FLOW_ERROR_TYPE_ACTION_NUM,
1363                                    NULL, "No action specified");
1364                 return -rte_errno;
1365         }
1366
1367         if (attrs) {
1368                 if (attrs->group) {
1369                         rte_flow_error_set(error, ENOTSUP,
1370                                            RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
1371                                            NULL,
1372                                            "priority groups are not supported");
1373                         return -rte_errno;
1374                 } else if (attrs->priority) {
1375                         rte_flow_error_set(error, ENOTSUP,
1376                                            RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
1377                                            NULL,
1378                                            "priorities are not supported");
1379                         return -rte_errno;
1380                 } else if (attrs->egress) {
1381                         rte_flow_error_set(error, ENOTSUP,
1382                                            RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
1383                                            NULL,
1384                                            "egress is not supported");
1385                         return -rte_errno;
1386                 } else if (attrs->transfer) {
1387                         rte_flow_error_set(error, ENOTSUP,
1388                                            RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
1389                                            NULL,
1390                                            "transfer is not supported");
1391                         return -rte_errno;
1392                 } else if (!attrs->ingress) {
1393                         rte_flow_error_set(error, ENOTSUP,
1394                                            RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
1395                                            NULL,
1396                                            "only ingress is supported");
1397                         return -rte_errno;
1398                 }
1399
1400         } else {
1401                 rte_flow_error_set(error, EINVAL,
1402                                    RTE_FLOW_ERROR_TYPE_ATTR,
1403                                    NULL, "No attribute specified");
1404                 return -rte_errno;
1405         }
1406
1407         /* Verify Actions. */
1408         enic_action_cap =  enic_get_action_cap(enic);
1409         for (action = &actions[0]; action->type != RTE_FLOW_ACTION_TYPE_END;
1410              action++) {
1411                 if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
1412                         continue;
1413                 else if (!enic_match_action(action, enic_action_cap->actions))
1414                         break;
1415         }
1416         if (action->type != RTE_FLOW_ACTION_TYPE_END) {
1417                 rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_ACTION,
1418                                    action, "Invalid action.");
1419                 return -rte_errno;
1420         }
1421         ret = enic_action_cap->copy_fn(actions, enic_action);
1422         if (ret) {
1423                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1424                            NULL, "Unsupported action.");
1425                 return -rte_errno;
1426         }
1427
1428         /* Verify Flow items. If copying the filter from flow format to enic
1429          * format fails, the flow is not supported
1430          */
1431         enic_filter_cap =  enic_get_filter_cap(enic);
1432         if (enic_filter_cap == NULL) {
1433                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
1434                            NULL, "Flow API not available");
1435                 return -rte_errno;
1436         }
1437         enic_filter->type = enic->flow_filter_mode;
1438         ret = enic_copy_filter(pattern, enic_filter_cap,
1439                                        enic_filter, error);
1440         return ret;
1441 }
1442
1443 /**
1444  * Push filter/action to the NIC.
1445  *
1446  * @param enic[in]
1447  *   Device structure pointer.
1448  * @param enic_filter[in]
1449  *   Internal NIC filter structure pointer.
1450  * @param enic_action[in]
1451  *   Internal NIC action structure pointer.
1452  * @param error[out]
1453  */
1454 static struct rte_flow *
1455 enic_flow_add_filter(struct enic *enic, struct filter_v2 *enic_filter,
1456                    struct filter_action_v2 *enic_action,
1457                    struct rte_flow_error *error)
1458 {
1459         struct rte_flow *flow;
1460         int err;
1461         uint16_t entry;
1462         int ctr_idx;
1463         int last_max_flow_ctr;
1464
1465         FLOW_TRACE();
1466
1467         flow = rte_calloc(__func__, 1, sizeof(*flow), 0);
1468         if (!flow) {
1469                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1470                                    NULL, "cannot allocate flow memory");
1471                 return NULL;
1472         }
1473
1474         flow->counter_idx = -1;
1475         last_max_flow_ctr = -1;
1476         if (enic_action->flags & FILTER_ACTION_COUNTER_FLAG) {
1477                 if (!vnic_dev_counter_alloc(enic->vdev, (uint32_t *)&ctr_idx)) {
1478                         rte_flow_error_set(error, ENOMEM,
1479                                            RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1480                                            NULL, "cannot allocate counter");
1481                         goto unwind_flow_alloc;
1482                 }
1483                 flow->counter_idx = ctr_idx;
1484                 enic_action->counter_index = ctr_idx;
1485
1486                 /* If index is the largest, increase the counter DMA size */
1487                 if (ctr_idx > enic->max_flow_counter) {
1488                         err = vnic_dev_counter_dma_cfg(enic->vdev,
1489                                                  VNIC_FLOW_COUNTER_UPDATE_MSECS,
1490                                                  ctr_idx + 1);
1491                         if (err) {
1492                                 rte_flow_error_set(error, -err,
1493                                            RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1494                                            NULL, "counter DMA config failed");
1495                                 goto unwind_ctr_alloc;
1496                         }
1497                         last_max_flow_ctr = enic->max_flow_counter;
1498                         enic->max_flow_counter = ctr_idx;
1499                 }
1500         }
1501
1502         /* entry[in] is the queue id, entry[out] is the filter Id for delete */
1503         entry = enic_action->rq_idx;
1504         err = vnic_dev_classifier(enic->vdev, CLSF_ADD, &entry, enic_filter,
1505                                   enic_action);
1506         if (err) {
1507                 rte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE,
1508                                    NULL, "vnic_dev_classifier error");
1509                 goto unwind_ctr_dma_cfg;
1510         }
1511
1512         flow->enic_filter_id = entry;
1513         flow->enic_filter = *enic_filter;
1514
1515         return flow;
1516
1517 /* unwind if there are errors */
1518 unwind_ctr_dma_cfg:
1519         if (last_max_flow_ctr != -1) {
1520                 /* reduce counter DMA size */
1521                 vnic_dev_counter_dma_cfg(enic->vdev,
1522                                          VNIC_FLOW_COUNTER_UPDATE_MSECS,
1523                                          last_max_flow_ctr + 1);
1524                 enic->max_flow_counter = last_max_flow_ctr;
1525         }
1526 unwind_ctr_alloc:
1527         if (flow->counter_idx != -1)
1528                 vnic_dev_counter_free(enic->vdev, ctr_idx);
1529 unwind_flow_alloc:
1530         rte_free(flow);
1531         return NULL;
1532 }
1533
1534 /**
1535  * Remove filter/action from the NIC.
1536  *
1537  * @param enic[in]
1538  *   Device structure pointer.
1539  * @param filter_id[in]
1540  *   Id of NIC filter.
1541  * @param enic_action[in]
1542  *   Internal NIC action structure pointer.
1543  * @param error[out]
1544  */
1545 static int
1546 enic_flow_del_filter(struct enic *enic, struct rte_flow *flow,
1547                    struct rte_flow_error *error)
1548 {
1549         u16 filter_id;
1550         int err;
1551
1552         FLOW_TRACE();
1553
1554         filter_id = flow->enic_filter_id;
1555         err = vnic_dev_classifier(enic->vdev, CLSF_DEL, &filter_id, NULL, NULL);
1556         if (err) {
1557                 rte_flow_error_set(error, -err, RTE_FLOW_ERROR_TYPE_HANDLE,
1558                                    NULL, "vnic_dev_classifier failed");
1559                 return -err;
1560         }
1561
1562         if (flow->counter_idx != -1) {
1563                 if (!vnic_dev_counter_free(enic->vdev, flow->counter_idx))
1564                         dev_err(enic, "counter free failed, idx: %d\n",
1565                                 flow->counter_idx);
1566                 flow->counter_idx = -1;
1567         }
1568         return 0;
1569 }
1570
1571 /*
1572  * The following functions are callbacks for Generic flow API.
1573  */
1574
1575 /**
1576  * Validate a flow supported by the NIC.
1577  *
1578  * @see rte_flow_validate()
1579  * @see rte_flow_ops
1580  */
1581 static int
1582 enic_flow_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attrs,
1583                    const struct rte_flow_item pattern[],
1584                    const struct rte_flow_action actions[],
1585                    struct rte_flow_error *error)
1586 {
1587         struct filter_v2 enic_filter;
1588         struct filter_action_v2 enic_action;
1589         int ret;
1590
1591         FLOW_TRACE();
1592
1593         ret = enic_flow_parse(dev, attrs, pattern, actions, error,
1594                                &enic_filter, &enic_action);
1595         if (!ret)
1596                 enic_dump_flow(&enic_action, &enic_filter);
1597         return ret;
1598 }
1599
1600 /**
1601  * Create a flow supported by the NIC.
1602  *
1603  * @see rte_flow_create()
1604  * @see rte_flow_ops
1605  */
1606 static struct rte_flow *
1607 enic_flow_create(struct rte_eth_dev *dev,
1608                  const struct rte_flow_attr *attrs,
1609                  const struct rte_flow_item pattern[],
1610                  const struct rte_flow_action actions[],
1611                  struct rte_flow_error *error)
1612 {
1613         int ret;
1614         struct filter_v2 enic_filter;
1615         struct filter_action_v2 enic_action;
1616         struct rte_flow *flow;
1617         struct enic *enic = pmd_priv(dev);
1618
1619         FLOW_TRACE();
1620
1621         ret = enic_flow_parse(dev, attrs, pattern, actions, error, &enic_filter,
1622                               &enic_action);
1623         if (ret < 0)
1624                 return NULL;
1625
1626         rte_spinlock_lock(&enic->flows_lock);
1627         flow = enic_flow_add_filter(enic, &enic_filter, &enic_action,
1628                                     error);
1629         if (flow)
1630                 LIST_INSERT_HEAD(&enic->flows, flow, next);
1631         rte_spinlock_unlock(&enic->flows_lock);
1632
1633         return flow;
1634 }
1635
1636 /**
1637  * Destroy a flow supported by the NIC.
1638  *
1639  * @see rte_flow_destroy()
1640  * @see rte_flow_ops
1641  */
1642 static int
1643 enic_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
1644                   __rte_unused struct rte_flow_error *error)
1645 {
1646         struct enic *enic = pmd_priv(dev);
1647
1648         FLOW_TRACE();
1649
1650         rte_spinlock_lock(&enic->flows_lock);
1651         enic_flow_del_filter(enic, flow, error);
1652         LIST_REMOVE(flow, next);
1653         rte_spinlock_unlock(&enic->flows_lock);
1654         rte_free(flow);
1655         return 0;
1656 }
1657
1658 /**
1659  * Flush all flows on the device.
1660  *
1661  * @see rte_flow_flush()
1662  * @see rte_flow_ops
1663  */
1664 static int
1665 enic_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
1666 {
1667         struct rte_flow *flow;
1668         struct enic *enic = pmd_priv(dev);
1669
1670         FLOW_TRACE();
1671
1672         rte_spinlock_lock(&enic->flows_lock);
1673
1674         while (!LIST_EMPTY(&enic->flows)) {
1675                 flow = LIST_FIRST(&enic->flows);
1676                 enic_flow_del_filter(enic, flow, error);
1677                 LIST_REMOVE(flow, next);
1678                 rte_free(flow);
1679         }
1680         rte_spinlock_unlock(&enic->flows_lock);
1681         return 0;
1682 }
1683
1684 static int
1685 enic_flow_query_count(struct rte_eth_dev *dev,
1686                       struct rte_flow *flow, void *data,
1687                       struct rte_flow_error *error)
1688 {
1689         struct enic *enic = pmd_priv(dev);
1690         struct rte_flow_query_count *query;
1691         uint64_t packets, bytes;
1692
1693         FLOW_TRACE();
1694
1695         if (flow->counter_idx == -1) {
1696                 return rte_flow_error_set(error, ENOTSUP,
1697                                           RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1698                                           NULL,
1699                                           "flow does not have counter");
1700         }
1701         query = (struct rte_flow_query_count *)data;
1702         if (!vnic_dev_counter_query(enic->vdev, flow->counter_idx,
1703                                     !!query->reset, &packets, &bytes)) {
1704                 return rte_flow_error_set
1705                         (error, EINVAL,
1706                          RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1707                          NULL,
1708                          "cannot read counter");
1709         }
1710         query->hits_set = 1;
1711         query->bytes_set = 1;
1712         query->hits = packets;
1713         query->bytes = bytes;
1714         return 0;
1715 }
1716
1717 static int
1718 enic_flow_query(struct rte_eth_dev *dev,
1719                 struct rte_flow *flow,
1720                 const struct rte_flow_action *actions,
1721                 void *data,
1722                 struct rte_flow_error *error)
1723 {
1724         int ret = 0;
1725
1726         FLOW_TRACE();
1727
1728         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1729                 switch (actions->type) {
1730                 case RTE_FLOW_ACTION_TYPE_VOID:
1731                         break;
1732                 case RTE_FLOW_ACTION_TYPE_COUNT:
1733                         ret = enic_flow_query_count(dev, flow, data, error);
1734                         break;
1735                 default:
1736                         return rte_flow_error_set(error, ENOTSUP,
1737                                                   RTE_FLOW_ERROR_TYPE_ACTION,
1738                                                   actions,
1739                                                   "action not supported");
1740                 }
1741                 if (ret < 0)
1742                         return ret;
1743         }
1744         return 0;
1745 }
1746
1747 /**
1748  * Flow callback registration.
1749  *
1750  * @see rte_flow_ops
1751  */
1752 const struct rte_flow_ops enic_flow_ops = {
1753         .validate = enic_flow_validate,
1754         .create = enic_flow_create,
1755         .destroy = enic_flow_destroy,
1756         .flush = enic_flow_flush,
1757         .query = enic_flow_query,
1758 };