net/mvpp2: build flow table key along with rule
[dpdk.git] / drivers / net / mvpp2 / mrvl_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Marvell International Ltd.
3  * Copyright(c) 2018 Semihalf.
4  * All rights reserved.
5  */
6
7 #include <rte_flow.h>
8 #include <rte_flow_driver.h>
9 #include <rte_malloc.h>
10 #include <rte_log.h>
11
12 #include <arpa/inet.h>
13
14 #include "mrvl_flow.h"
15 #include "mrvl_qos.h"
16
17 /** Number of rules in the classifier table. */
18 #define MRVL_CLS_MAX_NUM_RULES 20
19
20 /** Size of the classifier key and mask strings. */
21 #define MRVL_CLS_STR_SIZE_MAX 40
22
23 #define MRVL_VLAN_ID_MASK 0x0fff
24 #define MRVL_VLAN_PRI_MASK 0x7000
25 #define MRVL_IPV4_DSCP_MASK 0xfc
26 #define MRVL_IPV4_ADDR_MASK 0xffffffff
27 #define MRVL_IPV6_FLOW_MASK 0x0fffff
28
29 /**
30  * Allocate memory for classifier rule key and mask fields.
31  *
32  * @param field Pointer to the classifier rule.
33  * @returns 0 in case of success, negative value otherwise.
34  */
35 static int
36 mrvl_alloc_key_mask(struct pp2_cls_rule_key_field *field)
37 {
38         unsigned int id = rte_socket_id();
39
40         field->key = rte_zmalloc_socket(NULL, MRVL_CLS_STR_SIZE_MAX, 0, id);
41         if (!field->key)
42                 goto out;
43
44         field->mask = rte_zmalloc_socket(NULL, MRVL_CLS_STR_SIZE_MAX, 0, id);
45         if (!field->mask)
46                 goto out_mask;
47
48         return 0;
49 out_mask:
50         rte_free(field->key);
51 out:
52         field->key = NULL;
53         field->mask = NULL;
54         return -1;
55 }
56
57 /**
58  * Free memory allocated for classifier rule key and mask fields.
59  *
60  * @param field Pointer to the classifier rule.
61  */
62 static void
63 mrvl_free_key_mask(struct pp2_cls_rule_key_field *field)
64 {
65         rte_free(field->key);
66         rte_free(field->mask);
67         field->key = NULL;
68         field->mask = NULL;
69 }
70
71 /**
72  * Free memory allocated for all classifier rule key and mask fields.
73  *
74  * @param rule Pointer to the classifier table rule.
75  */
76 static void
77 mrvl_free_all_key_mask(struct pp2_cls_tbl_rule *rule)
78 {
79         int i;
80
81         for (i = 0; i < rule->num_fields; i++)
82                 mrvl_free_key_mask(&rule->fields[i]);
83         rule->num_fields = 0;
84 }
85
86 /*
87  * Initialize rte flow item parsing.
88  *
89  * @param item Pointer to the flow item.
90  * @param spec_ptr Pointer to the specific item pointer.
91  * @param mask_ptr Pointer to the specific item's mask pointer.
92  * @def_mask Pointer to the default mask.
93  * @size Size of the flow item.
94  * @error Pointer to the rte flow error.
95  * @returns 0 in case of success, negative value otherwise.
96  */
97 static int
98 mrvl_parse_init(const struct rte_flow_item *item,
99                 const void **spec_ptr,
100                 const void **mask_ptr,
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 zeros[size];
109
110         memset(zeros, 0, size);
111
112         if (item == NULL) {
113                 rte_flow_error_set(error, EINVAL,
114                                    RTE_FLOW_ERROR_TYPE_ITEM, NULL,
115                                    "NULL item\n");
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\n");
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\n");
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                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
148                                    NULL, "Spec should be specified\n");
149                 return -rte_errno;
150         }
151
152         /*
153          * If field values in "last" are either 0 or equal to the corresponding
154          * values in "spec" then they are ignored.
155          */
156         if (last != NULL &&
157             !memcmp(last, zeros, size) &&
158             memcmp(last, spec, size) != 0) {
159                 rte_flow_error_set(error, ENOTSUP,
160                                    RTE_FLOW_ERROR_TYPE_ITEM, NULL,
161                                    "Ranging is not supported\n");
162                 return -rte_errno;
163         }
164
165         *spec_ptr = spec;
166         *mask_ptr = mask;
167
168         return 0;
169 }
170
171 /**
172  * Parse the eth flow item.
173  *
174  * This will create classifier rule that matches either destination or source
175  * mac.
176  *
177  * @param spec Pointer to the specific flow item.
178  * @param mask Pointer to the specific flow item's mask.
179  * @param parse_dst Parse either destination or source mac address.
180  * @param flow Pointer to the flow.
181  * @return 0 in case of success, negative error value otherwise.
182  */
183 static int
184 mrvl_parse_mac(const struct rte_flow_item_eth *spec,
185                const struct rte_flow_item_eth *mask,
186                int parse_dst, struct rte_flow *flow)
187 {
188         struct pp2_cls_rule_key_field *key_field;
189         const uint8_t *k, *m;
190
191         if (parse_dst) {
192                 k = spec->dst.addr_bytes;
193                 m = mask->dst.addr_bytes;
194
195                 flow->table_key.proto_field[flow->rule.num_fields].field.eth =
196                         MV_NET_ETH_F_DA;
197         } else {
198                 k = spec->src.addr_bytes;
199                 m = mask->src.addr_bytes;
200
201                 flow->table_key.proto_field[flow->rule.num_fields].field.eth =
202                         MV_NET_ETH_F_SA;
203         }
204
205         key_field = &flow->rule.fields[flow->rule.num_fields];
206         mrvl_alloc_key_mask(key_field);
207         key_field->size = 6;
208
209         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX,
210                  "%02x:%02x:%02x:%02x:%02x:%02x",
211                  k[0], k[1], k[2], k[3], k[4], k[5]);
212
213         snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX,
214                  "%02x:%02x:%02x:%02x:%02x:%02x",
215                  m[0], m[1], m[2], m[3], m[4], m[5]);
216
217         flow->table_key.proto_field[flow->rule.num_fields].proto =
218                 MV_NET_PROTO_ETH;
219         flow->table_key.key_size += key_field->size;
220
221         flow->rule.num_fields += 1;
222
223         return 0;
224 }
225
226 /**
227  * Helper for parsing the eth flow item destination mac address.
228  *
229  * @param spec Pointer to the specific flow item.
230  * @param mask Pointer to the specific flow item's mask.
231  * @param flow Pointer to the flow.
232  * @return 0 in case of success, negative error value otherwise.
233  */
234 static inline int
235 mrvl_parse_dmac(const struct rte_flow_item_eth *spec,
236                 const struct rte_flow_item_eth *mask,
237                 struct rte_flow *flow)
238 {
239         return mrvl_parse_mac(spec, mask, 1, flow);
240 }
241
242 /**
243  * Helper for parsing the eth flow item source mac address.
244  *
245  * @param spec Pointer to the specific flow item.
246  * @param mask Pointer to the specific flow item's mask.
247  * @param flow Pointer to the flow.
248  * @return 0 in case of success, negative error value otherwise.
249  */
250 static inline int
251 mrvl_parse_smac(const struct rte_flow_item_eth *spec,
252                 const struct rte_flow_item_eth *mask,
253                 struct rte_flow *flow)
254 {
255         return mrvl_parse_mac(spec, mask, 0, flow);
256 }
257
258 /**
259  * Parse the ether type field of the eth flow item.
260  *
261  * @param spec Pointer to the specific flow item.
262  * @param mask Pointer to the specific flow item's mask.
263  * @param flow Pointer to the flow.
264  * @return 0 in case of success, negative error value otherwise.
265  */
266 static int
267 mrvl_parse_type(const struct rte_flow_item_eth *spec,
268                 const struct rte_flow_item_eth *mask __rte_unused,
269                 struct rte_flow *flow)
270 {
271         struct pp2_cls_rule_key_field *key_field;
272         uint16_t k;
273
274         key_field = &flow->rule.fields[flow->rule.num_fields];
275         mrvl_alloc_key_mask(key_field);
276         key_field->size = 2;
277
278         k = rte_be_to_cpu_16(spec->type);
279         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
280
281         flow->table_key.proto_field[flow->rule.num_fields].proto =
282                 MV_NET_PROTO_ETH;
283         flow->table_key.proto_field[flow->rule.num_fields].field.eth =
284                 MV_NET_ETH_F_TYPE;
285         flow->table_key.key_size += key_field->size;
286
287         flow->rule.num_fields += 1;
288
289         return 0;
290 }
291
292 /**
293  * Parse the vid field of the vlan rte flow item.
294  *
295  * This will create classifier rule that matches vid.
296  *
297  * @param spec Pointer to the specific flow item.
298  * @param mask Pointer to the specific flow item's mask.
299  * @param flow Pointer to the flow.
300  * @return 0 in case of success, negative error value otherwise.
301  */
302 static int
303 mrvl_parse_vlan_id(const struct rte_flow_item_vlan *spec,
304                    const struct rte_flow_item_vlan *mask __rte_unused,
305                    struct rte_flow *flow)
306 {
307         struct pp2_cls_rule_key_field *key_field;
308         uint16_t k;
309
310         key_field = &flow->rule.fields[flow->rule.num_fields];
311         mrvl_alloc_key_mask(key_field);
312         key_field->size = 2;
313
314         k = rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_ID_MASK;
315         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
316
317         flow->table_key.proto_field[flow->rule.num_fields].proto =
318                 MV_NET_PROTO_VLAN;
319         flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
320                 MV_NET_VLAN_F_ID;
321         flow->table_key.key_size += key_field->size;
322
323         flow->rule.num_fields += 1;
324
325         return 0;
326 }
327
328 /**
329  * Parse the pri field of the vlan rte flow item.
330  *
331  * This will create classifier rule that matches pri.
332  *
333  * @param spec Pointer to the specific flow item.
334  * @param mask Pointer to the specific flow item's mask.
335  * @param flow Pointer to the flow.
336  * @return 0 in case of success, negative error value otherwise.
337  */
338 static int
339 mrvl_parse_vlan_pri(const struct rte_flow_item_vlan *spec,
340                     const struct rte_flow_item_vlan *mask __rte_unused,
341                     struct rte_flow *flow)
342 {
343         struct pp2_cls_rule_key_field *key_field;
344         uint16_t k;
345
346         key_field = &flow->rule.fields[flow->rule.num_fields];
347         mrvl_alloc_key_mask(key_field);
348         key_field->size = 1;
349
350         k = (rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_PRI_MASK) >> 13;
351         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
352
353         flow->table_key.proto_field[flow->rule.num_fields].proto =
354                 MV_NET_PROTO_VLAN;
355         flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
356                 MV_NET_VLAN_F_PRI;
357         flow->table_key.key_size += key_field->size;
358
359         flow->rule.num_fields += 1;
360
361         return 0;
362 }
363
364 /**
365  * Parse the dscp field of the ipv4 rte flow item.
366  *
367  * This will create classifier rule that matches dscp field.
368  *
369  * @param spec Pointer to the specific flow item.
370  * @param mask Pointer to the specific flow item's mask.
371  * @param flow Pointer to the flow.
372  * @return 0 in case of success, negative error value otherwise.
373  */
374 static int
375 mrvl_parse_ip4_dscp(const struct rte_flow_item_ipv4 *spec,
376                     const struct rte_flow_item_ipv4 *mask,
377                     struct rte_flow *flow)
378 {
379         struct pp2_cls_rule_key_field *key_field;
380         uint8_t k, m;
381
382         key_field = &flow->rule.fields[flow->rule.num_fields];
383         mrvl_alloc_key_mask(key_field);
384         key_field->size = 1;
385
386         k = (spec->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) >> 2;
387         m = (mask->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) >> 2;
388         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
389         snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);
390
391         flow->table_key.proto_field[flow->rule.num_fields].proto =
392                 MV_NET_PROTO_IP4;
393         flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
394                 MV_NET_IP4_F_DSCP;
395         flow->table_key.key_size += key_field->size;
396
397         flow->rule.num_fields += 1;
398
399         return 0;
400 }
401
402 /**
403  * Parse either source or destination ip addresses of the ipv4 flow item.
404  *
405  * This will create classifier rule that matches either destination
406  * or source ip field.
407  *
408  * @param spec Pointer to the specific flow item.
409  * @param mask Pointer to the specific flow item's mask.
410  * @param parse_dst Parse either destination or source ip address.
411  * @param flow Pointer to the flow.
412  * @return 0 in case of success, negative error value otherwise.
413  */
414 static int
415 mrvl_parse_ip4_addr(const struct rte_flow_item_ipv4 *spec,
416                     const struct rte_flow_item_ipv4 *mask,
417                     int parse_dst, struct rte_flow *flow)
418 {
419         struct pp2_cls_rule_key_field *key_field;
420         struct in_addr k;
421         uint32_t m;
422
423         memset(&k, 0, sizeof(k));
424         if (parse_dst) {
425                 k.s_addr = spec->hdr.dst_addr;
426                 m = rte_be_to_cpu_32(mask->hdr.dst_addr);
427
428                 flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
429                         MV_NET_IP4_F_DA;
430         } else {
431                 k.s_addr = spec->hdr.src_addr;
432                 m = rte_be_to_cpu_32(mask->hdr.src_addr);
433
434                 flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
435                         MV_NET_IP4_F_SA;
436         }
437
438         key_field = &flow->rule.fields[flow->rule.num_fields];
439         mrvl_alloc_key_mask(key_field);
440         key_field->size = 4;
441
442         inet_ntop(AF_INET, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
443         snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "0x%x", m);
444
445         flow->table_key.proto_field[flow->rule.num_fields].proto =
446                 MV_NET_PROTO_IP4;
447         flow->table_key.key_size += key_field->size;
448
449         flow->rule.num_fields += 1;
450
451         return 0;
452 }
453
454 /**
455  * Helper for parsing destination ip of the ipv4 flow item.
456  *
457  * @param spec Pointer to the specific flow item.
458  * @param mask Pointer to the specific flow item's mask.
459  * @param flow Pointer to the flow.
460  * @return 0 in case of success, negative error value otherwise.
461  */
462 static inline int
463 mrvl_parse_ip4_dip(const struct rte_flow_item_ipv4 *spec,
464                    const struct rte_flow_item_ipv4 *mask,
465                    struct rte_flow *flow)
466 {
467         return mrvl_parse_ip4_addr(spec, mask, 1, flow);
468 }
469
470 /**
471  * Helper for parsing source ip of the ipv4 flow item.
472  *
473  * @param spec Pointer to the specific flow item.
474  * @param mask Pointer to the specific flow item's mask.
475  * @param flow Pointer to the flow.
476  * @return 0 in case of success, negative error value otherwise.
477  */
478 static inline int
479 mrvl_parse_ip4_sip(const struct rte_flow_item_ipv4 *spec,
480                    const struct rte_flow_item_ipv4 *mask,
481                    struct rte_flow *flow)
482 {
483         return mrvl_parse_ip4_addr(spec, mask, 0, flow);
484 }
485
486 /**
487  * Parse the proto field of the ipv4 rte flow item.
488  *
489  * This will create classifier rule that matches proto field.
490  *
491  * @param spec Pointer to the specific flow item.
492  * @param mask Pointer to the specific flow item's mask.
493  * @param flow Pointer to the flow.
494  * @return 0 in case of success, negative error value otherwise.
495  */
496 static int
497 mrvl_parse_ip4_proto(const struct rte_flow_item_ipv4 *spec,
498                      const struct rte_flow_item_ipv4 *mask __rte_unused,
499                      struct rte_flow *flow)
500 {
501         struct pp2_cls_rule_key_field *key_field;
502         uint8_t k = spec->hdr.next_proto_id;
503
504         key_field = &flow->rule.fields[flow->rule.num_fields];
505         mrvl_alloc_key_mask(key_field);
506         key_field->size = 1;
507
508         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
509
510         flow->table_key.proto_field[flow->rule.num_fields].proto =
511                 MV_NET_PROTO_IP4;
512         flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
513                 MV_NET_IP4_F_PROTO;
514         flow->table_key.key_size += key_field->size;
515
516         flow->rule.num_fields += 1;
517
518         return 0;
519 }
520
521 /**
522  * Parse either source or destination ip addresses of the ipv6 rte flow item.
523  *
524  * This will create classifier rule that matches either destination
525  * or source ip field.
526  *
527  * @param spec Pointer to the specific flow item.
528  * @param mask Pointer to the specific flow item's mask.
529  * @param parse_dst Parse either destination or source ipv6 address.
530  * @param flow Pointer to the flow.
531  * @return 0 in case of success, negative error value otherwise.
532  */
533 static int
534 mrvl_parse_ip6_addr(const struct rte_flow_item_ipv6 *spec,
535                const struct rte_flow_item_ipv6 *mask,
536                int parse_dst, struct rte_flow *flow)
537 {
538         struct pp2_cls_rule_key_field *key_field;
539         int size = sizeof(spec->hdr.dst_addr);
540         struct in6_addr k, m;
541
542         memset(&k, 0, sizeof(k));
543         if (parse_dst) {
544                 memcpy(k.s6_addr, spec->hdr.dst_addr, size);
545                 memcpy(m.s6_addr, mask->hdr.dst_addr, size);
546
547                 flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
548                         MV_NET_IP6_F_DA;
549         } else {
550                 memcpy(k.s6_addr, spec->hdr.src_addr, size);
551                 memcpy(m.s6_addr, mask->hdr.src_addr, size);
552
553                 flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
554                         MV_NET_IP6_F_SA;
555         }
556
557         key_field = &flow->rule.fields[flow->rule.num_fields];
558         mrvl_alloc_key_mask(key_field);
559         key_field->size = 16;
560
561         inet_ntop(AF_INET6, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
562         inet_ntop(AF_INET6, &m, (char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX);
563
564         flow->table_key.proto_field[flow->rule.num_fields].proto =
565                 MV_NET_PROTO_IP6;
566         flow->table_key.key_size += key_field->size;
567
568         flow->rule.num_fields += 1;
569
570         return 0;
571 }
572
573 /**
574  * Helper for parsing destination ip of the ipv6 flow item.
575  *
576  * @param spec Pointer to the specific flow item.
577  * @param mask Pointer to the specific flow item's mask.
578  * @param flow Pointer to the flow.
579  * @return 0 in case of success, negative error value otherwise.
580  */
581 static inline int
582 mrvl_parse_ip6_dip(const struct rte_flow_item_ipv6 *spec,
583                    const struct rte_flow_item_ipv6 *mask,
584                    struct rte_flow *flow)
585 {
586         return mrvl_parse_ip6_addr(spec, mask, 1, flow);
587 }
588
589 /**
590  * Helper for parsing source ip of the ipv6 flow item.
591  *
592  * @param spec Pointer to the specific flow item.
593  * @param mask Pointer to the specific flow item's mask.
594  * @param flow Pointer to the flow.
595  * @return 0 in case of success, negative error value otherwise.
596  */
597 static inline int
598 mrvl_parse_ip6_sip(const struct rte_flow_item_ipv6 *spec,
599                    const struct rte_flow_item_ipv6 *mask,
600                    struct rte_flow *flow)
601 {
602         return mrvl_parse_ip6_addr(spec, mask, 0, flow);
603 }
604
605 /**
606  * Parse the flow label of the ipv6 flow item.
607  *
608  * This will create classifier rule that matches flow field.
609  *
610  * @param spec Pointer to the specific flow item.
611  * @param mask Pointer to the specific flow item's mask.
612  * @param flow Pointer to the flow.
613  * @return 0 in case of success, negative error value otherwise.
614  */
615 static int
616 mrvl_parse_ip6_flow(const struct rte_flow_item_ipv6 *spec,
617                     const struct rte_flow_item_ipv6 *mask,
618                     struct rte_flow *flow)
619 {
620         struct pp2_cls_rule_key_field *key_field;
621         uint32_t k = rte_be_to_cpu_32(spec->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK,
622                  m = rte_be_to_cpu_32(mask->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK;
623
624         key_field = &flow->rule.fields[flow->rule.num_fields];
625         mrvl_alloc_key_mask(key_field);
626         key_field->size = 3;
627
628         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
629         snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);
630
631         flow->table_key.proto_field[flow->rule.num_fields].proto =
632                 MV_NET_PROTO_IP6;
633         flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
634                 MV_NET_IP6_F_FLOW;
635         flow->table_key.key_size += key_field->size;
636
637         flow->rule.num_fields += 1;
638
639         return 0;
640 }
641
642 /**
643  * Parse the next header of the ipv6 flow item.
644  *
645  * This will create classifier rule that matches next header field.
646  *
647  * @param spec Pointer to the specific flow item.
648  * @param mask Pointer to the specific flow item's mask.
649  * @param flow Pointer to the flow.
650  * @return 0 in case of success, negative error value otherwise.
651  */
652 static int
653 mrvl_parse_ip6_next_hdr(const struct rte_flow_item_ipv6 *spec,
654                         const struct rte_flow_item_ipv6 *mask __rte_unused,
655                         struct rte_flow *flow)
656 {
657         struct pp2_cls_rule_key_field *key_field;
658         uint8_t k = spec->hdr.proto;
659
660         key_field = &flow->rule.fields[flow->rule.num_fields];
661         mrvl_alloc_key_mask(key_field);
662         key_field->size = 1;
663
664         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
665
666         flow->table_key.proto_field[flow->rule.num_fields].proto =
667                 MV_NET_PROTO_IP6;
668         flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
669                 MV_NET_IP6_F_NEXT_HDR;
670         flow->table_key.key_size += key_field->size;
671
672         flow->rule.num_fields += 1;
673
674         return 0;
675 }
676
677 /**
678  * Parse destination or source port of the tcp flow item.
679  *
680  * This will create classifier rule that matches either destination or
681  * source tcp port.
682  *
683  * @param spec Pointer to the specific flow item.
684  * @param mask Pointer to the specific flow item's mask.
685  * @param parse_dst Parse either destination or source port.
686  * @param flow Pointer to the flow.
687  * @return 0 in case of success, negative error value otherwise.
688  */
689 static int
690 mrvl_parse_tcp_port(const struct rte_flow_item_tcp *spec,
691                     const struct rte_flow_item_tcp *mask __rte_unused,
692                     int parse_dst, struct rte_flow *flow)
693 {
694         struct pp2_cls_rule_key_field *key_field;
695         uint16_t k;
696
697         key_field = &flow->rule.fields[flow->rule.num_fields];
698         mrvl_alloc_key_mask(key_field);
699         key_field->size = 2;
700
701         if (parse_dst) {
702                 k = rte_be_to_cpu_16(spec->hdr.dst_port);
703
704                 flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
705                         MV_NET_TCP_F_DP;
706         } else {
707                 k = rte_be_to_cpu_16(spec->hdr.src_port);
708
709                 flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
710                         MV_NET_TCP_F_SP;
711         }
712
713         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
714
715         flow->table_key.proto_field[flow->rule.num_fields].proto =
716                 MV_NET_PROTO_TCP;
717         flow->table_key.key_size += key_field->size;
718
719         flow->rule.num_fields += 1;
720
721         return 0;
722 }
723
724 /**
725  * Helper for parsing the tcp source port of the tcp flow item.
726  *
727  * @param spec Pointer to the specific flow item.
728  * @param mask Pointer to the specific flow item's mask.
729  * @param flow Pointer to the flow.
730  * @return 0 in case of success, negative error value otherwise.
731  */
732 static inline int
733 mrvl_parse_tcp_sport(const struct rte_flow_item_tcp *spec,
734                      const struct rte_flow_item_tcp *mask,
735                      struct rte_flow *flow)
736 {
737         return mrvl_parse_tcp_port(spec, mask, 0, flow);
738 }
739
740 /**
741  * Helper for parsing the tcp destination port of the tcp flow item.
742  *
743  * @param spec Pointer to the specific flow item.
744  * @param mask Pointer to the specific flow item's mask.
745  * @param flow Pointer to the flow.
746  * @return 0 in case of success, negative error value otherwise.
747  */
748 static inline int
749 mrvl_parse_tcp_dport(const struct rte_flow_item_tcp *spec,
750                      const struct rte_flow_item_tcp *mask,
751                      struct rte_flow *flow)
752 {
753         return mrvl_parse_tcp_port(spec, mask, 1, flow);
754 }
755
756 /**
757  * Parse destination or source port of the udp flow item.
758  *
759  * This will create classifier rule that matches either destination or
760  * source udp port.
761  *
762  * @param spec Pointer to the specific flow item.
763  * @param mask Pointer to the specific flow item's mask.
764  * @param parse_dst Parse either destination or source port.
765  * @param flow Pointer to the flow.
766  * @return 0 in case of success, negative error value otherwise.
767  */
768 static int
769 mrvl_parse_udp_port(const struct rte_flow_item_udp *spec,
770                     const struct rte_flow_item_udp *mask __rte_unused,
771                     int parse_dst, struct rte_flow *flow)
772 {
773         struct pp2_cls_rule_key_field *key_field;
774         uint16_t k;
775
776         key_field = &flow->rule.fields[flow->rule.num_fields];
777         mrvl_alloc_key_mask(key_field);
778         key_field->size = 2;
779
780         if (parse_dst) {
781                 k = rte_be_to_cpu_16(spec->hdr.dst_port);
782
783                 flow->table_key.proto_field[flow->rule.num_fields].field.udp =
784                         MV_NET_UDP_F_DP;
785         } else {
786                 k = rte_be_to_cpu_16(spec->hdr.src_port);
787
788                 flow->table_key.proto_field[flow->rule.num_fields].field.udp =
789                         MV_NET_UDP_F_SP;
790         }
791
792         snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
793
794         flow->table_key.proto_field[flow->rule.num_fields].proto =
795                 MV_NET_PROTO_UDP;
796         flow->table_key.key_size += key_field->size;
797
798         flow->rule.num_fields += 1;
799
800         return 0;
801 }
802
803 /**
804  * Helper for parsing the udp source port of the udp flow item.
805  *
806  * @param spec Pointer to the specific flow item.
807  * @param mask Pointer to the specific flow item's mask.
808  * @param flow Pointer to the flow.
809  * @return 0 in case of success, negative error value otherwise.
810  */
811 static inline int
812 mrvl_parse_udp_sport(const struct rte_flow_item_udp *spec,
813                      const struct rte_flow_item_udp *mask,
814                      struct rte_flow *flow)
815 {
816         return mrvl_parse_udp_port(spec, mask, 0, flow);
817 }
818
819 /**
820  * Helper for parsing the udp destination port of the udp flow item.
821  *
822  * @param spec Pointer to the specific flow item.
823  * @param mask Pointer to the specific flow item's mask.
824  * @param flow Pointer to the flow.
825  * @return 0 in case of success, negative error value otherwise.
826  */
827 static inline int
828 mrvl_parse_udp_dport(const struct rte_flow_item_udp *spec,
829                      const struct rte_flow_item_udp *mask,
830                      struct rte_flow *flow)
831 {
832         return mrvl_parse_udp_port(spec, mask, 1, flow);
833 }
834
835 /**
836  * Parse eth flow item.
837  *
838  * @param item Pointer to the flow item.
839  * @param flow Pointer to the flow.
840  * @param error Pointer to the flow error.
841  * @returns 0 on success, negative value otherwise.
842  */
843 static int
844 mrvl_parse_eth(const struct rte_flow_item *item, struct rte_flow *flow,
845                struct rte_flow_error *error)
846 {
847         const struct rte_flow_item_eth *spec = NULL, *mask = NULL;
848         struct rte_ether_addr zero;
849         int ret;
850
851         ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
852                               &rte_flow_item_eth_mask,
853                               sizeof(struct rte_flow_item_eth), error);
854         if (ret)
855                 return ret;
856
857         memset(&zero, 0, sizeof(zero));
858
859         if (memcmp(&mask->dst, &zero, sizeof(mask->dst))) {
860                 ret = mrvl_parse_dmac(spec, mask, flow);
861                 if (ret)
862                         goto out;
863         }
864
865         if (memcmp(&mask->src, &zero, sizeof(mask->src))) {
866                 ret = mrvl_parse_smac(spec, mask, flow);
867                 if (ret)
868                         goto out;
869         }
870
871         if (mask->type) {
872                 MRVL_LOG(WARNING, "eth type mask is ignored");
873                 ret = mrvl_parse_type(spec, mask, flow);
874                 if (ret)
875                         goto out;
876         }
877
878         return 0;
879 out:
880         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
881                            "Reached maximum number of fields in cls tbl key\n");
882         return -rte_errno;
883 }
884
885 /**
886  * Parse vlan flow item.
887  *
888  * @param item Pointer to the flow item.
889  * @param flow Pointer to the flow.
890  * @param error Pointer to the flow error.
891  * @returns 0 on success, negative value otherwise.
892  */
893 static int
894 mrvl_parse_vlan(const struct rte_flow_item *item,
895                 struct rte_flow *flow,
896                 struct rte_flow_error *error)
897 {
898         const struct rte_flow_item_vlan *spec = NULL, *mask = NULL;
899         uint16_t m;
900         int ret, i;
901
902         ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
903                               &rte_flow_item_vlan_mask,
904                               sizeof(struct rte_flow_item_vlan), error);
905         if (ret)
906                 return ret;
907
908         m = rte_be_to_cpu_16(mask->tci);
909         if (m & MRVL_VLAN_ID_MASK) {
910                 MRVL_LOG(WARNING, "vlan id mask is ignored");
911                 ret = mrvl_parse_vlan_id(spec, mask, flow);
912                 if (ret)
913                         goto out;
914         }
915
916         if (m & MRVL_VLAN_PRI_MASK) {
917                 MRVL_LOG(WARNING, "vlan pri mask is ignored");
918                 ret = mrvl_parse_vlan_pri(spec, mask, flow);
919                 if (ret)
920                         goto out;
921         }
922
923         if (mask->inner_type) {
924                 struct rte_flow_item_eth spec_eth = {
925                         .type = spec->inner_type,
926                 };
927                 struct rte_flow_item_eth mask_eth = {
928                         .type = mask->inner_type,
929                 };
930
931                 /* TPID is not supported so if ETH_TYPE was selected,
932                  * error is return. else, classify eth-type with the tpid value
933                  */
934                 for (i = 0; i < flow->rule.num_fields; i++)
935                         if (flow->table_key.proto_field[i].proto ==
936                             MV_NET_PROTO_ETH &&
937                             flow->table_key.proto_field[i].field.eth ==
938                             MV_NET_ETH_F_TYPE) {
939                                 rte_flow_error_set(error, ENOTSUP,
940                                                    RTE_FLOW_ERROR_TYPE_ITEM,
941                                                    item,
942                                                    "VLAN TPID matching is not supported");
943                                 return -rte_errno;
944                         }
945
946                 MRVL_LOG(WARNING, "inner eth type mask is ignored");
947                 ret = mrvl_parse_type(&spec_eth, &mask_eth, flow);
948                 if (ret)
949                         goto out;
950         }
951
952         return 0;
953 out:
954         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
955                            "Reached maximum number of fields in cls tbl key\n");
956         return -rte_errno;
957 }
958
959 /**
960  * Parse ipv4 flow item.
961  *
962  * @param item Pointer to the flow item.
963  * @param flow Pointer to the flow.
964  * @param error Pointer to the flow error.
965  * @returns 0 on success, negative value otherwise.
966  */
967 static int
968 mrvl_parse_ip4(const struct rte_flow_item *item,
969                struct rte_flow *flow,
970                struct rte_flow_error *error)
971 {
972         const struct rte_flow_item_ipv4 *spec = NULL, *mask = NULL;
973         int ret;
974
975         ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
976                               &rte_flow_item_ipv4_mask,
977                               sizeof(struct rte_flow_item_ipv4), error);
978         if (ret)
979                 return ret;
980
981         if (mask->hdr.version_ihl ||
982             mask->hdr.total_length ||
983             mask->hdr.packet_id ||
984             mask->hdr.fragment_offset ||
985             mask->hdr.time_to_live ||
986             mask->hdr.hdr_checksum) {
987                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
988                                    NULL, "Not supported by classifier\n");
989                 return -rte_errno;
990         }
991
992         if (mask->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) {
993                 ret = mrvl_parse_ip4_dscp(spec, mask, flow);
994                 if (ret)
995                         goto out;
996         }
997
998         if (mask->hdr.src_addr) {
999                 ret = mrvl_parse_ip4_sip(spec, mask, flow);
1000                 if (ret)
1001                         goto out;
1002         }
1003
1004         if (mask->hdr.dst_addr) {
1005                 ret = mrvl_parse_ip4_dip(spec, mask, flow);
1006                 if (ret)
1007                         goto out;
1008         }
1009
1010         if (mask->hdr.next_proto_id) {
1011                 MRVL_LOG(WARNING, "next proto id mask is ignored");
1012                 ret = mrvl_parse_ip4_proto(spec, mask, flow);
1013                 if (ret)
1014                         goto out;
1015         }
1016
1017         return 0;
1018 out:
1019         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1020                            "Reached maximum number of fields in cls tbl key\n");
1021         return -rte_errno;
1022 }
1023
1024 /**
1025  * Parse ipv6 flow item.
1026  *
1027  * @param item Pointer to the flow item.
1028  * @param flow Pointer to the flow.
1029  * @param error Pointer to the flow error.
1030  * @returns 0 on success, negative value otherwise.
1031  */
1032 static int
1033 mrvl_parse_ip6(const struct rte_flow_item *item,
1034                struct rte_flow *flow,
1035                struct rte_flow_error *error)
1036 {
1037         const struct rte_flow_item_ipv6 *spec = NULL, *mask = NULL;
1038         struct rte_ipv6_hdr zero;
1039         uint32_t flow_mask;
1040         int ret;
1041
1042         ret = mrvl_parse_init(item, (const void **)&spec,
1043                               (const void **)&mask,
1044                               &rte_flow_item_ipv6_mask,
1045                               sizeof(struct rte_flow_item_ipv6),
1046                               error);
1047         if (ret)
1048                 return ret;
1049
1050         memset(&zero, 0, sizeof(zero));
1051
1052         if (mask->hdr.payload_len ||
1053             mask->hdr.hop_limits) {
1054                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1055                                    NULL, "Not supported by classifier\n");
1056                 return -rte_errno;
1057         }
1058
1059         if (memcmp(mask->hdr.src_addr,
1060                    zero.src_addr, sizeof(mask->hdr.src_addr))) {
1061                 ret = mrvl_parse_ip6_sip(spec, mask, flow);
1062                 if (ret)
1063                         goto out;
1064         }
1065
1066         if (memcmp(mask->hdr.dst_addr,
1067                    zero.dst_addr, sizeof(mask->hdr.dst_addr))) {
1068                 ret = mrvl_parse_ip6_dip(spec, mask, flow);
1069                 if (ret)
1070                         goto out;
1071         }
1072
1073         flow_mask = rte_be_to_cpu_32(mask->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK;
1074         if (flow_mask) {
1075                 ret = mrvl_parse_ip6_flow(spec, mask, flow);
1076                 if (ret)
1077                         goto out;
1078         }
1079
1080         if (mask->hdr.proto) {
1081                 MRVL_LOG(WARNING, "next header mask is ignored");
1082                 ret = mrvl_parse_ip6_next_hdr(spec, mask, flow);
1083                 if (ret)
1084                         goto out;
1085         }
1086
1087         return 0;
1088 out:
1089         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1090                            "Reached maximum number of fields in cls tbl key\n");
1091         return -rte_errno;
1092 }
1093
1094 /**
1095  * Parse tcp flow item.
1096  *
1097  * @param item Pointer to the flow item.
1098  * @param flow Pointer to the flow.
1099  * @param error Pointer to the flow error.
1100  * @returns 0 on success, negative value otherwise.
1101  */
1102 static int
1103 mrvl_parse_tcp(const struct rte_flow_item *item,
1104                struct rte_flow *flow,
1105                struct rte_flow_error *error)
1106 {
1107         const struct rte_flow_item_tcp *spec = NULL, *mask = NULL;
1108         int ret;
1109
1110         ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
1111                               &rte_flow_item_tcp_mask,
1112                               sizeof(struct rte_flow_item_tcp), error);
1113         if (ret)
1114                 return ret;
1115
1116         if (mask->hdr.sent_seq ||
1117             mask->hdr.recv_ack ||
1118             mask->hdr.data_off ||
1119             mask->hdr.tcp_flags ||
1120             mask->hdr.rx_win ||
1121             mask->hdr.cksum ||
1122             mask->hdr.tcp_urp) {
1123                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1124                                    NULL, "Not supported by classifier\n");
1125                 return -rte_errno;
1126         }
1127
1128         if (mask->hdr.src_port) {
1129                 MRVL_LOG(WARNING, "tcp sport mask is ignored");
1130                 ret = mrvl_parse_tcp_sport(spec, mask, flow);
1131                 if (ret)
1132                         goto out;
1133         }
1134
1135         if (mask->hdr.dst_port) {
1136                 MRVL_LOG(WARNING, "tcp dport mask is ignored");
1137                 ret = mrvl_parse_tcp_dport(spec, mask, flow);
1138                 if (ret)
1139                         goto out;
1140         }
1141
1142         return 0;
1143 out:
1144         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1145                            "Reached maximum number of fields in cls tbl key\n");
1146         return -rte_errno;
1147 }
1148
1149 /**
1150  * Parse udp flow item.
1151  *
1152  * @param item Pointer to the flow item.
1153  * @param flow Pointer to the flow.
1154  * @param error Pointer to the flow error.
1155  * @returns 0 on success, negative value otherwise.
1156  */
1157 static int
1158 mrvl_parse_udp(const struct rte_flow_item *item,
1159                struct rte_flow *flow,
1160                struct rte_flow_error *error)
1161 {
1162         const struct rte_flow_item_udp *spec = NULL, *mask = NULL;
1163         int ret;
1164
1165         ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
1166                               &rte_flow_item_udp_mask,
1167                               sizeof(struct rte_flow_item_udp), error);
1168         if (ret)
1169                 return ret;
1170
1171         if (mask->hdr.dgram_len ||
1172             mask->hdr.dgram_cksum) {
1173                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1174                                    NULL, "Not supported by classifier\n");
1175                 return -rte_errno;
1176         }
1177
1178         if (mask->hdr.src_port) {
1179                 MRVL_LOG(WARNING, "udp sport mask is ignored");
1180                 ret = mrvl_parse_udp_sport(spec, mask, flow);
1181                 if (ret)
1182                         goto out;
1183         }
1184
1185         if (mask->hdr.dst_port) {
1186                 MRVL_LOG(WARNING, "udp dport mask is ignored");
1187                 ret = mrvl_parse_udp_dport(spec, mask, flow);
1188                 if (ret)
1189                         goto out;
1190         }
1191
1192         return 0;
1193 out:
1194         rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1195                            "Reached maximum number of fields in cls tbl key\n");
1196         return -rte_errno;
1197 }
1198
1199 /**
1200  * Structure used to map specific flow pattern to the pattern parse callback
1201  * which will iterate over each pattern item and extract relevant data.
1202  */
1203 static const struct {
1204         const enum rte_flow_item_type pattern_type;
1205         int (*parse)(const struct rte_flow_item *pattern,
1206                 struct rte_flow *flow,
1207                 struct rte_flow_error *error);
1208 } mrvl_patterns[] = {
1209         { RTE_FLOW_ITEM_TYPE_ETH, mrvl_parse_eth },
1210         { RTE_FLOW_ITEM_TYPE_VLAN, mrvl_parse_vlan },
1211         { RTE_FLOW_ITEM_TYPE_IPV4, mrvl_parse_ip4 },
1212         { RTE_FLOW_ITEM_TYPE_IPV6, mrvl_parse_ip6 },
1213         { RTE_FLOW_ITEM_TYPE_TCP, mrvl_parse_tcp },
1214         { RTE_FLOW_ITEM_TYPE_UDP, mrvl_parse_udp },
1215         { RTE_FLOW_ITEM_TYPE_END, NULL }
1216 };
1217
1218 /**
1219  * Parse flow attribute.
1220  *
1221  * This will check whether the provided attribute's flags are supported.
1222  *
1223  * @param priv Unused
1224  * @param attr Pointer to the flow attribute.
1225  * @param flow Unused
1226  * @param error Pointer to the flow error.
1227  * @returns 0 in case of success, negative value otherwise.
1228  */
1229 static int
1230 mrvl_flow_parse_attr(struct mrvl_priv *priv __rte_unused,
1231                      const struct rte_flow_attr *attr,
1232                      struct rte_flow *flow __rte_unused,
1233                      struct rte_flow_error *error)
1234 {
1235         if (!attr) {
1236                 rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
1237                                    NULL, "NULL attribute");
1238                 return -rte_errno;
1239         }
1240
1241         if (attr->group) {
1242                 rte_flow_error_set(error, ENOTSUP,
1243                                    RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
1244                                    "Groups are not supported");
1245                 return -rte_errno;
1246         }
1247         if (attr->priority) {
1248                 rte_flow_error_set(error, ENOTSUP,
1249                                    RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
1250                                    "Priorities are not supported");
1251                 return -rte_errno;
1252         }
1253         if (!attr->ingress) {
1254                 rte_flow_error_set(error, ENOTSUP,
1255                                    RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
1256                                    "Only ingress is supported");
1257                 return -rte_errno;
1258         }
1259         if (attr->egress) {
1260                 rte_flow_error_set(error, ENOTSUP,
1261                                    RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
1262                                    "Egress is not supported");
1263                 return -rte_errno;
1264         }
1265         if (attr->transfer) {
1266                 rte_flow_error_set(error, ENOTSUP,
1267                                    RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
1268                                    "Transfer is not supported");
1269                 return -rte_errno;
1270         }
1271
1272         return 0;
1273 }
1274
1275 /**
1276  * Parse flow pattern.
1277  *
1278  * Specific classifier rule will be created as well.
1279  *
1280  * @param priv Unused
1281  * @param pattern Pointer to the flow pattern.
1282  * @param flow Pointer to the flow.
1283  * @param error Pointer to the flow error.
1284  * @returns 0 in case of success, negative value otherwise.
1285  */
1286 static int
1287 mrvl_flow_parse_pattern(struct mrvl_priv *priv __rte_unused,
1288                         const struct rte_flow_item pattern[],
1289                         struct rte_flow *flow,
1290                         struct rte_flow_error *error)
1291 {
1292         unsigned int i, j;
1293         int ret;
1294
1295         for (i = 0; pattern[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {
1296                 if (pattern[i].type == RTE_FLOW_ITEM_TYPE_VOID)
1297                         continue;
1298                 for (j = 0; mrvl_patterns[j].pattern_type !=
1299                         RTE_FLOW_ITEM_TYPE_END; j++) {
1300                         if (mrvl_patterns[j].pattern_type != pattern[i].type)
1301                                 continue;
1302
1303                         if (flow->rule.num_fields >=
1304                             PP2_CLS_TBL_MAX_NUM_FIELDS) {
1305                                 rte_flow_error_set(error, ENOSPC,
1306                                                    RTE_FLOW_ERROR_TYPE_ITEM_NUM,
1307                                                    NULL,
1308                                                    "too many pattern (max %d)");
1309                                 return -rte_errno;
1310                         }
1311
1312                         ret = mrvl_patterns[j].parse(&pattern[i], flow, error);
1313                         if (ret) {
1314                                 mrvl_free_all_key_mask(&flow->rule);
1315                                 return ret;
1316                         }
1317                         break;
1318                 }
1319                 if (mrvl_patterns[j].pattern_type == RTE_FLOW_ITEM_TYPE_END) {
1320                         rte_flow_error_set(error, ENOTSUP,
1321                                            RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1322                                            "Unsupported pattern");
1323                         return -rte_errno;
1324                 }
1325         }
1326
1327         flow->table_key.num_fields = flow->rule.num_fields;
1328
1329         return 0;
1330 }
1331
1332 /**
1333  * Parse flow actions.
1334  *
1335  * @param priv Pointer to the port's private data.
1336  * @param actions Pointer the action table.
1337  * @param flow Pointer to the flow.
1338  * @param error Pointer to the flow error.
1339  * @returns 0 in case of success, negative value otherwise.
1340  */
1341 static int
1342 mrvl_flow_parse_actions(struct mrvl_priv *priv,
1343                         const struct rte_flow_action actions[],
1344                         struct rte_flow *flow,
1345                         struct rte_flow_error *error)
1346 {
1347         const struct rte_flow_action *action = actions;
1348         int specified = 0;
1349
1350         for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
1351                 if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
1352                         continue;
1353
1354                 if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
1355                         flow->cos.ppio = priv->ppio;
1356                         flow->cos.tc = 0;
1357                         flow->action.type = PP2_CLS_TBL_ACT_DROP;
1358                         flow->action.cos = &flow->cos;
1359                         specified++;
1360                 } else if (action->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
1361                         const struct rte_flow_action_queue *q =
1362                                 (const struct rte_flow_action_queue *)
1363                                 action->conf;
1364
1365                         if (q->index > priv->nb_rx_queues) {
1366                                 rte_flow_error_set(error, EINVAL,
1367                                                 RTE_FLOW_ERROR_TYPE_ACTION,
1368                                                 NULL,
1369                                                 "Queue index out of range");
1370                                 return -rte_errno;
1371                         }
1372
1373                         if (priv->rxq_map[q->index].tc == MRVL_UNKNOWN_TC) {
1374                                 /*
1375                                  * Unknown TC mapping, mapping will not have
1376                                  * a correct queue.
1377                                  */
1378                                 MRVL_LOG(ERR,
1379                                         "Unknown TC mapping for queue %hu eth%hhu",
1380                                         q->index, priv->ppio_id);
1381
1382                                 rte_flow_error_set(error, EFAULT,
1383                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1384                                                 NULL, NULL);
1385                                 return -rte_errno;
1386                         }
1387
1388                         MRVL_LOG(DEBUG,
1389                                 "Action: Assign packets to queue %d, tc:%d, q:%d",
1390                                 q->index, priv->rxq_map[q->index].tc,
1391                                 priv->rxq_map[q->index].inq);
1392
1393                         flow->cos.ppio = priv->ppio;
1394                         flow->cos.tc = priv->rxq_map[q->index].tc;
1395                         flow->action.type = PP2_CLS_TBL_ACT_DONE;
1396                         flow->action.cos = &flow->cos;
1397                         specified++;
1398                 } else if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
1399                         const struct rte_flow_action_meter *meter;
1400                         struct mrvl_mtr *mtr;
1401
1402                         meter = action->conf;
1403                         if (!meter)
1404                                 return -rte_flow_error_set(error, EINVAL,
1405                                                 RTE_FLOW_ERROR_TYPE_ACTION,
1406                                                 NULL, "Invalid meter\n");
1407
1408                         LIST_FOREACH(mtr, &priv->mtrs, next)
1409                                 if (mtr->mtr_id == meter->mtr_id)
1410                                         break;
1411
1412                         if (!mtr)
1413                                 return -rte_flow_error_set(error, EINVAL,
1414                                                 RTE_FLOW_ERROR_TYPE_ACTION,
1415                                                 NULL,
1416                                                 "Meter id does not exist\n");
1417
1418                         if (!mtr->shared && mtr->refcnt)
1419                                 return -rte_flow_error_set(error, EPERM,
1420                                                 RTE_FLOW_ERROR_TYPE_ACTION,
1421                                                 NULL,
1422                                                 "Meter cannot be shared\n");
1423
1424                         /*
1425                          * In case cos has already been set
1426                          * do not modify it.
1427                          */
1428                         if (!flow->cos.ppio) {
1429                                 flow->cos.ppio = priv->ppio;
1430                                 flow->cos.tc = 0;
1431                         }
1432
1433                         flow->action.type = PP2_CLS_TBL_ACT_DONE;
1434                         flow->action.cos = &flow->cos;
1435                         flow->action.plcr = mtr->enabled ? mtr->plcr : NULL;
1436                         flow->mtr = mtr;
1437                         mtr->refcnt++;
1438                         specified++;
1439                 } else {
1440                         rte_flow_error_set(error, ENOTSUP,
1441                                            RTE_FLOW_ERROR_TYPE_ACTION, NULL,
1442                                            "Action not supported");
1443                         return -rte_errno;
1444                 }
1445         }
1446
1447         if (!specified) {
1448                 rte_flow_error_set(error, EINVAL,
1449                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1450                                    "Action not specified");
1451                 return -rte_errno;
1452         }
1453
1454         return 0;
1455 }
1456
1457 /**
1458  * Parse flow attribute, pattern and actions.
1459  *
1460  * @param priv Pointer to the port's private data.
1461  * @param attr Pointer to the flow attribute.
1462  * @param pattern Pointer to the flow pattern.
1463  * @param actions Pointer to the flow actions.
1464  * @param flow Pointer to the flow.
1465  * @param error Pointer to the flow error.
1466  * @returns 0 on success, negative value otherwise.
1467  */
1468 static int
1469 mrvl_flow_parse(struct mrvl_priv *priv, const struct rte_flow_attr *attr,
1470                 const struct rte_flow_item pattern[],
1471                 const struct rte_flow_action actions[],
1472                 struct rte_flow *flow,
1473                 struct rte_flow_error *error)
1474 {
1475         int ret;
1476
1477         ret = mrvl_flow_parse_attr(priv, attr, flow, error);
1478         if (ret)
1479                 return ret;
1480
1481         ret = mrvl_flow_parse_pattern(priv, pattern, flow, error);
1482         if (ret)
1483                 return ret;
1484
1485         return mrvl_flow_parse_actions(priv, actions, flow, error);
1486 }
1487
1488 /**
1489  * Get engine type for the given flow.
1490  *
1491  * @param field Pointer to the flow.
1492  * @returns The type of the engine.
1493  */
1494 static inline enum pp2_cls_tbl_type
1495 mrvl_engine_type(const struct rte_flow *flow)
1496 {
1497         int i, size = 0;
1498
1499         for (i = 0; i < flow->rule.num_fields; i++)
1500                 size += flow->rule.fields[i].size;
1501
1502         /*
1503          * For maskable engine type the key size must be up to 8 bytes.
1504          * For keys with size bigger than 8 bytes, engine type must
1505          * be set to exact match.
1506          */
1507         if (size > 8)
1508                 return PP2_CLS_TBL_EXACT_MATCH;
1509
1510         return PP2_CLS_TBL_MASKABLE;
1511 }
1512
1513 /**
1514  * Create classifier table.
1515  *
1516  * @param dev Pointer to the device.
1517  * @param flow Pointer to the very first flow.
1518  * @returns 0 in case of success, negative value otherwise.
1519  */
1520 static int
1521 mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
1522 {
1523         struct mrvl_priv *priv = dev->data->dev_private;
1524         struct pp2_cls_tbl_key *key = &priv->cls_tbl_params.key;
1525         int ret;
1526
1527         if (priv->cls_tbl) {
1528                 pp2_cls_tbl_deinit(priv->cls_tbl);
1529                 priv->cls_tbl = NULL;
1530         }
1531
1532         memset(&priv->cls_tbl_params, 0, sizeof(priv->cls_tbl_params));
1533
1534         priv->cls_tbl_params.type = mrvl_engine_type(first_flow);
1535         MRVL_LOG(INFO, "Setting cls search engine type to %s",
1536                         priv->cls_tbl_params.type == PP2_CLS_TBL_EXACT_MATCH ?
1537                         "exact" : "maskable");
1538         priv->cls_tbl_params.max_num_rules = MRVL_CLS_MAX_NUM_RULES;
1539         priv->cls_tbl_params.default_act.type = PP2_CLS_TBL_ACT_DONE;
1540         priv->cls_tbl_params.default_act.cos = &first_flow->cos;
1541         memcpy(key, &first_flow->table_key, sizeof(struct pp2_cls_tbl_key));
1542
1543         ret = pp2_cls_tbl_init(&priv->cls_tbl_params, &priv->cls_tbl);
1544
1545         return ret;
1546 }
1547
1548 /**
1549  * Check whether new flow can be added to the table
1550  *
1551  * @param priv Pointer to the port's private data.
1552  * @param flow Pointer to the new flow.
1553  * @return 1 in case flow can be added, 0 otherwise.
1554  */
1555 static inline int
1556 mrvl_flow_can_be_added(struct mrvl_priv *priv, const struct rte_flow *flow)
1557 {
1558         int same = memcmp(&flow->table_key, &priv->cls_tbl_params.key,
1559                           sizeof(struct pp2_cls_tbl_key)) == 0;
1560
1561         return same && mrvl_engine_type(flow) == priv->cls_tbl_params.type;
1562 }
1563
1564 /**
1565  * DPDK flow create callback called when flow is to be created.
1566  *
1567  * @param dev Pointer to the device.
1568  * @param attr Pointer to the flow attribute.
1569  * @param pattern Pointer to the flow pattern.
1570  * @param actions Pointer to the flow actions.
1571  * @param error Pointer to the flow error.
1572  * @returns Pointer to the created flow in case of success, NULL otherwise.
1573  */
1574 static struct rte_flow *
1575 mrvl_flow_create(struct rte_eth_dev *dev,
1576                  const struct rte_flow_attr *attr,
1577                  const struct rte_flow_item pattern[],
1578                  const struct rte_flow_action actions[],
1579                  struct rte_flow_error *error)
1580 {
1581         struct mrvl_priv *priv = dev->data->dev_private;
1582         struct rte_flow *flow, *first;
1583         int ret;
1584
1585         if (!dev->data->dev_started) {
1586                 rte_flow_error_set(error, EINVAL,
1587                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1588                                    "Port must be started first\n");
1589                 return NULL;
1590         }
1591
1592         flow = rte_zmalloc_socket(NULL, sizeof(*flow), 0, rte_socket_id());
1593         if (!flow)
1594                 return NULL;
1595
1596         ret = mrvl_flow_parse(priv, attr, pattern, actions, flow, error);
1597         if (ret)
1598                 goto out;
1599
1600         /*
1601          * Four cases here:
1602          *
1603          * 1. In case table does not exist - create one.
1604          * 2. In case table exists, is empty and new flow cannot be added
1605          *    recreate table.
1606          * 3. In case table is not empty and new flow matches table format
1607          *    add it.
1608          * 4. Otherwise flow cannot be added.
1609          */
1610         first = LIST_FIRST(&priv->flows);
1611         if (!priv->cls_tbl) {
1612                 ret = mrvl_create_cls_table(dev, flow);
1613         } else if (!first && !mrvl_flow_can_be_added(priv, flow)) {
1614                 ret = mrvl_create_cls_table(dev, flow);
1615         } else if (mrvl_flow_can_be_added(priv, flow)) {
1616                 ret = 0;
1617         } else {
1618                 rte_flow_error_set(error, EINVAL,
1619                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1620                                    "Pattern does not match cls table format\n");
1621                 goto out;
1622         }
1623
1624         if (ret) {
1625                 rte_flow_error_set(error, EINVAL,
1626                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1627                                    "Failed to create cls table\n");
1628                 goto out;
1629         }
1630
1631         ret = pp2_cls_tbl_add_rule(priv->cls_tbl, &flow->rule, &flow->action);
1632         if (ret) {
1633                 rte_flow_error_set(error, EINVAL,
1634                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1635                                    "Failed to add rule\n");
1636                 goto out;
1637         }
1638
1639         LIST_INSERT_HEAD(&priv->flows, flow, next);
1640
1641         return flow;
1642 out:
1643         rte_free(flow);
1644         return NULL;
1645 }
1646
1647 /**
1648  * Remove classifier rule associated with given flow.
1649  *
1650  * @param priv Pointer to the port's private data.
1651  * @param flow Pointer to the flow.
1652  * @param error Pointer to the flow error.
1653  * @returns 0 in case of success, negative value otherwise.
1654  */
1655 static int
1656 mrvl_flow_remove(struct mrvl_priv *priv, struct rte_flow *flow,
1657                  struct rte_flow_error *error)
1658 {
1659         int ret;
1660
1661         if (!priv->cls_tbl) {
1662                 rte_flow_error_set(error, EINVAL,
1663                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1664                                    "Classifier table not initialized");
1665                 return -rte_errno;
1666         }
1667
1668         ret = pp2_cls_tbl_remove_rule(priv->cls_tbl, &flow->rule);
1669         if (ret) {
1670                 rte_flow_error_set(error, EINVAL,
1671                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1672                                    "Failed to remove rule");
1673                 return -rte_errno;
1674         }
1675
1676         mrvl_free_all_key_mask(&flow->rule);
1677
1678         if (flow->mtr) {
1679                 flow->mtr->refcnt--;
1680                 flow->mtr = NULL;
1681         }
1682
1683         return 0;
1684 }
1685
1686 /**
1687  * DPDK flow destroy callback called when flow is to be removed.
1688  *
1689  * @param dev Pointer to the device.
1690  * @param flow Pointer to the flow.
1691  * @param error Pointer to the flow error.
1692  * @returns 0 in case of success, negative value otherwise.
1693  */
1694 static int
1695 mrvl_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
1696                   struct rte_flow_error *error)
1697 {
1698         struct mrvl_priv *priv = dev->data->dev_private;
1699         struct rte_flow *f;
1700         int ret;
1701
1702         LIST_FOREACH(f, &priv->flows, next) {
1703                 if (f == flow)
1704                         break;
1705         }
1706
1707         if (!flow) {
1708                 rte_flow_error_set(error, EINVAL,
1709                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1710                                    "Rule was not found");
1711                 return -rte_errno;
1712         }
1713
1714         LIST_REMOVE(f, next);
1715
1716         ret = mrvl_flow_remove(priv, flow, error);
1717         if (ret)
1718                 return ret;
1719
1720         rte_free(flow);
1721
1722         return 0;
1723 }
1724
1725 /**
1726  * DPDK flow callback called to verify given attribute, pattern and actions.
1727  *
1728  * @param dev Pointer to the device.
1729  * @param attr Pointer to the flow attribute.
1730  * @param pattern Pointer to the flow pattern.
1731  * @param actions Pointer to the flow actions.
1732  * @param error Pointer to the flow error.
1733  * @returns 0 on success, negative value otherwise.
1734  */
1735 static int
1736 mrvl_flow_validate(struct rte_eth_dev *dev,
1737                    const struct rte_flow_attr *attr,
1738                    const struct rte_flow_item pattern[],
1739                    const struct rte_flow_action actions[],
1740                    struct rte_flow_error *error)
1741 {
1742         static struct rte_flow *flow;
1743
1744         flow = mrvl_flow_create(dev, attr, pattern, actions, error);
1745         if (!flow)
1746                 return -rte_errno;
1747
1748         mrvl_flow_destroy(dev, flow, error);
1749
1750         return 0;
1751 }
1752
1753 /**
1754  * DPDK flow flush callback called when flows are to be flushed.
1755  *
1756  * @param dev Pointer to the device.
1757  * @param error Pointer to the flow error.
1758  * @returns 0 in case of success, negative value otherwise.
1759  */
1760 static int
1761 mrvl_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
1762 {
1763         struct mrvl_priv *priv = dev->data->dev_private;
1764
1765         while (!LIST_EMPTY(&priv->flows)) {
1766                 struct rte_flow *flow = LIST_FIRST(&priv->flows);
1767                 int ret = mrvl_flow_remove(priv, flow, error);
1768                 if (ret)
1769                         return ret;
1770
1771                 LIST_REMOVE(flow, next);
1772                 rte_free(flow);
1773         }
1774
1775         if (priv->cls_tbl) {
1776                 pp2_cls_tbl_deinit(priv->cls_tbl);
1777                 priv->cls_tbl = NULL;
1778         }
1779
1780         return 0;
1781 }
1782
1783 /**
1784  * DPDK flow isolate callback called to isolate port.
1785  *
1786  * @param dev Pointer to the device.
1787  * @param enable Pass 0/1 to disable/enable port isolation.
1788  * @param error Pointer to the flow error.
1789  * @returns 0 in case of success, negative value otherwise.
1790  */
1791 static int
1792 mrvl_flow_isolate(struct rte_eth_dev *dev, int enable,
1793                   struct rte_flow_error *error)
1794 {
1795         struct mrvl_priv *priv = dev->data->dev_private;
1796
1797         if (dev->data->dev_started) {
1798                 rte_flow_error_set(error, EBUSY,
1799                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1800                                    NULL, "Port must be stopped first\n");
1801                 return -rte_errno;
1802         }
1803
1804         priv->isolated = enable;
1805
1806         return 0;
1807 }
1808
1809 const struct rte_flow_ops mrvl_flow_ops = {
1810         .validate = mrvl_flow_validate,
1811         .create = mrvl_flow_create,
1812         .destroy = mrvl_flow_destroy,
1813         .flush = mrvl_flow_flush,
1814         .isolate = mrvl_flow_isolate
1815 };
1816
1817 /**
1818  * Initialize flow resources.
1819  *
1820  * @param dev Pointer to the device.
1821  */
1822 void
1823 mrvl_flow_init(struct rte_eth_dev *dev)
1824 {
1825         struct mrvl_priv *priv = dev->data->dev_private;
1826
1827         LIST_INIT(&priv->flows);
1828 }
1829
1830 /**
1831  * Cleanup flow resources.
1832  *
1833  * @param dev Pointer to the device.
1834  */
1835 void
1836 mrvl_flow_deinit(struct rte_eth_dev *dev)
1837 {
1838         mrvl_flow_flush(dev, NULL);
1839 }