06c05a0f58e777b75700be0d36ed18c29cb11ca1
[dpdk.git] / drivers / net / dpaa2 / dpaa2_flow.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2018-2020 NXP
3  */
4
5 #include <sys/queue.h>
6 #include <stdio.h>
7 #include <errno.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <stdarg.h>
12
13 #include <rte_ethdev.h>
14 #include <rte_log.h>
15 #include <rte_malloc.h>
16 #include <rte_flow_driver.h>
17 #include <rte_tailq.h>
18
19 #include <fsl_dpni.h>
20 #include <fsl_dpkg.h>
21
22 #include <dpaa2_ethdev.h>
23 #include <dpaa2_pmd_logs.h>
24
25 /* Workaround to discriminate the UDP/TCP/SCTP
26  * with next protocol of l3.
27  * MC/WRIOP are not able to identify
28  * the l4 protocol with l4 ports.
29  */
30 int mc_l4_port_identification;
31
32 enum flow_rule_ipaddr_type {
33         FLOW_NONE_IPADDR,
34         FLOW_IPV4_ADDR,
35         FLOW_IPV6_ADDR
36 };
37
38 struct flow_rule_ipaddr {
39         enum flow_rule_ipaddr_type ipaddr_type;
40         int qos_ipsrc_offset;
41         int qos_ipdst_offset;
42         int fs_ipsrc_offset;
43         int fs_ipdst_offset;
44 };
45
46 struct rte_flow {
47         LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
48         struct dpni_rule_cfg qos_rule;
49         struct dpni_rule_cfg fs_rule;
50         uint8_t key_size;
51         uint8_t tc_id; /** Traffic Class ID. */
52         uint8_t tc_index; /** index within this Traffic Class. */
53         enum rte_flow_action_type action;
54         uint16_t flow_id;
55         /* Special for IP address to specify the offset
56          * in key/mask.
57          */
58         struct flow_rule_ipaddr ipaddr_rule;
59         struct dpni_fs_action_cfg action_cfg;
60 };
61
62 static const
63 enum rte_flow_item_type dpaa2_supported_pattern_type[] = {
64         RTE_FLOW_ITEM_TYPE_END,
65         RTE_FLOW_ITEM_TYPE_ETH,
66         RTE_FLOW_ITEM_TYPE_VLAN,
67         RTE_FLOW_ITEM_TYPE_IPV4,
68         RTE_FLOW_ITEM_TYPE_IPV6,
69         RTE_FLOW_ITEM_TYPE_ICMP,
70         RTE_FLOW_ITEM_TYPE_UDP,
71         RTE_FLOW_ITEM_TYPE_TCP,
72         RTE_FLOW_ITEM_TYPE_SCTP,
73         RTE_FLOW_ITEM_TYPE_GRE,
74 };
75
76 static const
77 enum rte_flow_action_type dpaa2_supported_action_type[] = {
78         RTE_FLOW_ACTION_TYPE_END,
79         RTE_FLOW_ACTION_TYPE_QUEUE,
80         RTE_FLOW_ACTION_TYPE_RSS
81 };
82
83 /* Max of enum rte_flow_item_type + 1, for both IPv4 and IPv6*/
84 #define DPAA2_FLOW_ITEM_TYPE_GENERIC_IP (RTE_FLOW_ITEM_TYPE_META + 1)
85
86 enum rte_filter_type dpaa2_filter_type = RTE_ETH_FILTER_NONE;
87
88 #ifndef __cplusplus
89 static const struct rte_flow_item_eth dpaa2_flow_item_eth_mask = {
90         .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
91         .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
92         .type = RTE_BE16(0xffff),
93 };
94
95 static const struct rte_flow_item_vlan dpaa2_flow_item_vlan_mask = {
96         .tci = RTE_BE16(0xffff),
97 };
98
99 static const struct rte_flow_item_ipv4 dpaa2_flow_item_ipv4_mask = {
100         .hdr.src_addr = RTE_BE32(0xffffffff),
101         .hdr.dst_addr = RTE_BE32(0xffffffff),
102         .hdr.next_proto_id = 0xff,
103 };
104
105 static const struct rte_flow_item_ipv6 dpaa2_flow_item_ipv6_mask = {
106         .hdr = {
107                 .src_addr =
108                         "\xff\xff\xff\xff\xff\xff\xff\xff"
109                         "\xff\xff\xff\xff\xff\xff\xff\xff",
110                 .dst_addr =
111                         "\xff\xff\xff\xff\xff\xff\xff\xff"
112                         "\xff\xff\xff\xff\xff\xff\xff\xff",
113                 .proto = 0xff
114         },
115 };
116
117 static const struct rte_flow_item_icmp dpaa2_flow_item_icmp_mask = {
118         .hdr.icmp_type = 0xff,
119         .hdr.icmp_code = 0xff,
120 };
121
122 static const struct rte_flow_item_udp dpaa2_flow_item_udp_mask = {
123         .hdr = {
124                 .src_port = RTE_BE16(0xffff),
125                 .dst_port = RTE_BE16(0xffff),
126         },
127 };
128
129 static const struct rte_flow_item_tcp dpaa2_flow_item_tcp_mask = {
130         .hdr = {
131                 .src_port = RTE_BE16(0xffff),
132                 .dst_port = RTE_BE16(0xffff),
133         },
134 };
135
136 static const struct rte_flow_item_sctp dpaa2_flow_item_sctp_mask = {
137         .hdr = {
138                 .src_port = RTE_BE16(0xffff),
139                 .dst_port = RTE_BE16(0xffff),
140         },
141 };
142
143 static const struct rte_flow_item_gre dpaa2_flow_item_gre_mask = {
144         .protocol = RTE_BE16(0xffff),
145 };
146
147 #endif
148
149
150 static inline void dpaa2_flow_extract_key_set(
151         struct dpaa2_key_info *key_info, int index, uint8_t size)
152 {
153         key_info->key_size[index] = size;
154         if (index > 0) {
155                 key_info->key_offset[index] =
156                         key_info->key_offset[index - 1] +
157                         key_info->key_size[index - 1];
158         } else {
159                 key_info->key_offset[index] = 0;
160         }
161         key_info->key_total_size += size;
162 }
163
164 static int dpaa2_flow_extract_add(
165         struct dpaa2_key_extract *key_extract,
166         enum net_prot prot,
167         uint32_t field, uint8_t field_size)
168 {
169         int index, ip_src = -1, ip_dst = -1;
170         struct dpkg_profile_cfg *dpkg = &key_extract->dpkg;
171         struct dpaa2_key_info *key_info = &key_extract->key_info;
172
173         if (dpkg->num_extracts >=
174                 DPKG_MAX_NUM_OF_EXTRACTS) {
175                 DPAA2_PMD_WARN("Number of extracts overflows");
176                 return -1;
177         }
178         /* Before reorder, the IP SRC and IP DST are already last
179          * extract(s).
180          */
181         for (index = 0; index < dpkg->num_extracts; index++) {
182                 if (dpkg->extracts[index].extract.from_hdr.prot ==
183                         NET_PROT_IP) {
184                         if (dpkg->extracts[index].extract.from_hdr.field ==
185                                 NH_FLD_IP_SRC) {
186                                 ip_src = index;
187                         }
188                         if (dpkg->extracts[index].extract.from_hdr.field ==
189                                 NH_FLD_IP_DST) {
190                                 ip_dst = index;
191                         }
192                 }
193         }
194
195         if (ip_src >= 0)
196                 RTE_ASSERT((ip_src + 2) >= dpkg->num_extracts);
197
198         if (ip_dst >= 0)
199                 RTE_ASSERT((ip_dst + 2) >= dpkg->num_extracts);
200
201         if (prot == NET_PROT_IP &&
202                 (field == NH_FLD_IP_SRC ||
203                 field == NH_FLD_IP_DST)) {
204                 index = dpkg->num_extracts;
205         } else {
206                 if (ip_src >= 0 && ip_dst >= 0)
207                         index = dpkg->num_extracts - 2;
208                 else if (ip_src >= 0 || ip_dst >= 0)
209                         index = dpkg->num_extracts - 1;
210                 else
211                         index = dpkg->num_extracts;
212         }
213
214         dpkg->extracts[index].type =    DPKG_EXTRACT_FROM_HDR;
215         dpkg->extracts[index].extract.from_hdr.type = DPKG_FULL_FIELD;
216         dpkg->extracts[index].extract.from_hdr.prot = prot;
217         dpkg->extracts[index].extract.from_hdr.field = field;
218         if (prot == NET_PROT_IP &&
219                 (field == NH_FLD_IP_SRC ||
220                 field == NH_FLD_IP_DST)) {
221                 dpaa2_flow_extract_key_set(key_info, index, 0);
222         } else {
223                 dpaa2_flow_extract_key_set(key_info, index, field_size);
224         }
225
226         if (prot == NET_PROT_IP) {
227                 if (field == NH_FLD_IP_SRC) {
228                         if (key_info->ipv4_dst_offset >= 0) {
229                                 key_info->ipv4_src_offset =
230                                         key_info->ipv4_dst_offset +
231                                         NH_FLD_IPV4_ADDR_SIZE;
232                         } else {
233                                 key_info->ipv4_src_offset =
234                                         key_info->key_offset[index - 1] +
235                                                 key_info->key_size[index - 1];
236                         }
237                         if (key_info->ipv6_dst_offset >= 0) {
238                                 key_info->ipv6_src_offset =
239                                         key_info->ipv6_dst_offset +
240                                         NH_FLD_IPV6_ADDR_SIZE;
241                         } else {
242                                 key_info->ipv6_src_offset =
243                                         key_info->key_offset[index - 1] +
244                                                 key_info->key_size[index - 1];
245                         }
246                 } else if (field == NH_FLD_IP_DST) {
247                         if (key_info->ipv4_src_offset >= 0) {
248                                 key_info->ipv4_dst_offset =
249                                         key_info->ipv4_src_offset +
250                                         NH_FLD_IPV4_ADDR_SIZE;
251                         } else {
252                                 key_info->ipv4_dst_offset =
253                                         key_info->key_offset[index - 1] +
254                                                 key_info->key_size[index - 1];
255                         }
256                         if (key_info->ipv6_src_offset >= 0) {
257                                 key_info->ipv6_dst_offset =
258                                         key_info->ipv6_src_offset +
259                                         NH_FLD_IPV6_ADDR_SIZE;
260                         } else {
261                                 key_info->ipv6_dst_offset =
262                                         key_info->key_offset[index - 1] +
263                                                 key_info->key_size[index - 1];
264                         }
265                 }
266         }
267
268         if (index == dpkg->num_extracts) {
269                 dpkg->num_extracts++;
270                 return 0;
271         }
272
273         if (ip_src >= 0) {
274                 ip_src++;
275                 dpkg->extracts[ip_src].type =
276                         DPKG_EXTRACT_FROM_HDR;
277                 dpkg->extracts[ip_src].extract.from_hdr.type =
278                         DPKG_FULL_FIELD;
279                 dpkg->extracts[ip_src].extract.from_hdr.prot =
280                         NET_PROT_IP;
281                 dpkg->extracts[ip_src].extract.from_hdr.field =
282                         NH_FLD_IP_SRC;
283                 dpaa2_flow_extract_key_set(key_info, ip_src, 0);
284                 key_info->ipv4_src_offset += field_size;
285                 key_info->ipv6_src_offset += field_size;
286         }
287         if (ip_dst >= 0) {
288                 ip_dst++;
289                 dpkg->extracts[ip_dst].type =
290                         DPKG_EXTRACT_FROM_HDR;
291                 dpkg->extracts[ip_dst].extract.from_hdr.type =
292                         DPKG_FULL_FIELD;
293                 dpkg->extracts[ip_dst].extract.from_hdr.prot =
294                         NET_PROT_IP;
295                 dpkg->extracts[ip_dst].extract.from_hdr.field =
296                         NH_FLD_IP_DST;
297                 dpaa2_flow_extract_key_set(key_info, ip_dst, 0);
298                 key_info->ipv4_dst_offset += field_size;
299                 key_info->ipv6_dst_offset += field_size;
300         }
301
302         dpkg->num_extracts++;
303
304         return 0;
305 }
306
307 /* Protocol discrimination.
308  * Discriminate IPv4/IPv6/vLan by Eth type.
309  * Discriminate UDP/TCP/ICMP by next proto of IP.
310  */
311 static inline int
312 dpaa2_flow_proto_discrimination_extract(
313         struct dpaa2_key_extract *key_extract,
314         enum rte_flow_item_type type)
315 {
316         if (type == RTE_FLOW_ITEM_TYPE_ETH) {
317                 return dpaa2_flow_extract_add(
318                                 key_extract, NET_PROT_ETH,
319                                 NH_FLD_ETH_TYPE,
320                                 sizeof(rte_be16_t));
321         } else if (type == (enum rte_flow_item_type)
322                 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) {
323                 return dpaa2_flow_extract_add(
324                                 key_extract, NET_PROT_IP,
325                                 NH_FLD_IP_PROTO,
326                                 NH_FLD_IP_PROTO_SIZE);
327         }
328
329         return -1;
330 }
331
332 static inline int dpaa2_flow_extract_search(
333         struct dpkg_profile_cfg *dpkg,
334         enum net_prot prot, uint32_t field)
335 {
336         int i;
337
338         for (i = 0; i < dpkg->num_extracts; i++) {
339                 if (dpkg->extracts[i].extract.from_hdr.prot == prot &&
340                         dpkg->extracts[i].extract.from_hdr.field == field) {
341                         return i;
342                 }
343         }
344
345         return -1;
346 }
347
348 static inline int dpaa2_flow_extract_key_offset(
349         struct dpaa2_key_extract *key_extract,
350         enum net_prot prot, uint32_t field)
351 {
352         int i;
353         struct dpkg_profile_cfg *dpkg = &key_extract->dpkg;
354         struct dpaa2_key_info *key_info = &key_extract->key_info;
355
356         if (prot == NET_PROT_IPV4 ||
357                 prot == NET_PROT_IPV6)
358                 i = dpaa2_flow_extract_search(dpkg, NET_PROT_IP, field);
359         else
360                 i = dpaa2_flow_extract_search(dpkg, prot, field);
361
362         if (i >= 0) {
363                 if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_SRC)
364                         return key_info->ipv4_src_offset;
365                 else if (prot == NET_PROT_IPV4 && field == NH_FLD_IP_DST)
366                         return key_info->ipv4_dst_offset;
367                 else if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_SRC)
368                         return key_info->ipv6_src_offset;
369                 else if (prot == NET_PROT_IPV6 && field == NH_FLD_IP_DST)
370                         return key_info->ipv6_dst_offset;
371                 else
372                         return key_info->key_offset[i];
373         } else {
374                 return -1;
375         }
376 }
377
378 struct proto_discrimination {
379         enum rte_flow_item_type type;
380         union {
381                 rte_be16_t eth_type;
382                 uint8_t ip_proto;
383         };
384 };
385
386 static int
387 dpaa2_flow_proto_discrimination_rule(
388         struct dpaa2_dev_priv *priv, struct rte_flow *flow,
389         struct proto_discrimination proto, int group)
390 {
391         enum net_prot prot;
392         uint32_t field;
393         int offset;
394         size_t key_iova;
395         size_t mask_iova;
396         rte_be16_t eth_type;
397         uint8_t ip_proto;
398
399         if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
400                 prot = NET_PROT_ETH;
401                 field = NH_FLD_ETH_TYPE;
402         } else if (proto.type == DPAA2_FLOW_ITEM_TYPE_GENERIC_IP) {
403                 prot = NET_PROT_IP;
404                 field = NH_FLD_IP_PROTO;
405         } else {
406                 DPAA2_PMD_ERR(
407                         "Only Eth and IP support to discriminate next proto.");
408                 return -1;
409         }
410
411         offset = dpaa2_flow_extract_key_offset(&priv->extract.qos_key_extract,
412                         prot, field);
413         if (offset < 0) {
414                 DPAA2_PMD_ERR("QoS prot %d field %d extract failed",
415                                 prot, field);
416                 return -1;
417         }
418         key_iova = flow->qos_rule.key_iova + offset;
419         mask_iova = flow->qos_rule.mask_iova + offset;
420         if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
421                 eth_type = proto.eth_type;
422                 memcpy((void *)key_iova, (const void *)(&eth_type),
423                         sizeof(rte_be16_t));
424                 eth_type = 0xffff;
425                 memcpy((void *)mask_iova, (const void *)(&eth_type),
426                         sizeof(rte_be16_t));
427         } else {
428                 ip_proto = proto.ip_proto;
429                 memcpy((void *)key_iova, (const void *)(&ip_proto),
430                         sizeof(uint8_t));
431                 ip_proto = 0xff;
432                 memcpy((void *)mask_iova, (const void *)(&ip_proto),
433                         sizeof(uint8_t));
434         }
435
436         offset = dpaa2_flow_extract_key_offset(
437                         &priv->extract.tc_key_extract[group],
438                         prot, field);
439         if (offset < 0) {
440                 DPAA2_PMD_ERR("FS prot %d field %d extract failed",
441                                 prot, field);
442                 return -1;
443         }
444         key_iova = flow->fs_rule.key_iova + offset;
445         mask_iova = flow->fs_rule.mask_iova + offset;
446
447         if (proto.type == RTE_FLOW_ITEM_TYPE_ETH) {
448                 eth_type = proto.eth_type;
449                 memcpy((void *)key_iova, (const void *)(&eth_type),
450                         sizeof(rte_be16_t));
451                 eth_type = 0xffff;
452                 memcpy((void *)mask_iova, (const void *)(&eth_type),
453                         sizeof(rte_be16_t));
454         } else {
455                 ip_proto = proto.ip_proto;
456                 memcpy((void *)key_iova, (const void *)(&ip_proto),
457                         sizeof(uint8_t));
458                 ip_proto = 0xff;
459                 memcpy((void *)mask_iova, (const void *)(&ip_proto),
460                         sizeof(uint8_t));
461         }
462
463         return 0;
464 }
465
466 static inline int
467 dpaa2_flow_rule_data_set(
468         struct dpaa2_key_extract *key_extract,
469         struct dpni_rule_cfg *rule,
470         enum net_prot prot, uint32_t field,
471         const void *key, const void *mask, int size)
472 {
473         int offset = dpaa2_flow_extract_key_offset(key_extract,
474                                 prot, field);
475
476         if (offset < 0) {
477                 DPAA2_PMD_ERR("prot %d, field %d extract failed",
478                         prot, field);
479                 return -1;
480         }
481         memcpy((void *)(size_t)(rule->key_iova + offset), key, size);
482         memcpy((void *)(size_t)(rule->mask_iova + offset), mask, size);
483
484         return 0;
485 }
486
487 static inline int
488 _dpaa2_flow_rule_move_ipaddr_tail(
489         struct dpaa2_key_extract *key_extract,
490         struct dpni_rule_cfg *rule, int src_offset,
491         uint32_t field, bool ipv4)
492 {
493         size_t key_src;
494         size_t mask_src;
495         size_t key_dst;
496         size_t mask_dst;
497         int dst_offset, len;
498         enum net_prot prot;
499         char tmp[NH_FLD_IPV6_ADDR_SIZE];
500
501         if (field != NH_FLD_IP_SRC &&
502                 field != NH_FLD_IP_DST) {
503                 DPAA2_PMD_ERR("Field of IP addr reorder must be IP SRC/DST");
504                 return -1;
505         }
506         if (ipv4)
507                 prot = NET_PROT_IPV4;
508         else
509                 prot = NET_PROT_IPV6;
510         dst_offset = dpaa2_flow_extract_key_offset(key_extract,
511                                 prot, field);
512         if (dst_offset < 0) {
513                 DPAA2_PMD_ERR("Field %d reorder extract failed", field);
514                 return -1;
515         }
516         key_src = rule->key_iova + src_offset;
517         mask_src = rule->mask_iova + src_offset;
518         key_dst = rule->key_iova + dst_offset;
519         mask_dst = rule->mask_iova + dst_offset;
520         if (ipv4)
521                 len = sizeof(rte_be32_t);
522         else
523                 len = NH_FLD_IPV6_ADDR_SIZE;
524
525         memcpy(tmp, (char *)key_src, len);
526         memcpy((char *)key_dst, tmp, len);
527
528         memcpy(tmp, (char *)mask_src, len);
529         memcpy((char *)mask_dst, tmp, len);
530
531         return 0;
532 }
533
534 static inline int
535 dpaa2_flow_rule_move_ipaddr_tail(
536         struct rte_flow *flow, struct dpaa2_dev_priv *priv,
537         int fs_group)
538 {
539         int ret;
540         enum net_prot prot;
541
542         if (flow->ipaddr_rule.ipaddr_type == FLOW_NONE_IPADDR)
543                 return 0;
544
545         if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR)
546                 prot = NET_PROT_IPV4;
547         else
548                 prot = NET_PROT_IPV6;
549
550         if (flow->ipaddr_rule.qos_ipsrc_offset >= 0) {
551                 ret = _dpaa2_flow_rule_move_ipaddr_tail(
552                                 &priv->extract.qos_key_extract,
553                                 &flow->qos_rule,
554                                 flow->ipaddr_rule.qos_ipsrc_offset,
555                                 NH_FLD_IP_SRC, prot == NET_PROT_IPV4);
556                 if (ret) {
557                         DPAA2_PMD_ERR("QoS src address reorder failed");
558                         return -1;
559                 }
560                 flow->ipaddr_rule.qos_ipsrc_offset =
561                         dpaa2_flow_extract_key_offset(
562                                 &priv->extract.qos_key_extract,
563                                 prot, NH_FLD_IP_SRC);
564         }
565
566         if (flow->ipaddr_rule.qos_ipdst_offset >= 0) {
567                 ret = _dpaa2_flow_rule_move_ipaddr_tail(
568                                 &priv->extract.qos_key_extract,
569                                 &flow->qos_rule,
570                                 flow->ipaddr_rule.qos_ipdst_offset,
571                                 NH_FLD_IP_DST, prot == NET_PROT_IPV4);
572                 if (ret) {
573                         DPAA2_PMD_ERR("QoS dst address reorder failed");
574                         return -1;
575                 }
576                 flow->ipaddr_rule.qos_ipdst_offset =
577                         dpaa2_flow_extract_key_offset(
578                                 &priv->extract.qos_key_extract,
579                                 prot, NH_FLD_IP_DST);
580         }
581
582         if (flow->ipaddr_rule.fs_ipsrc_offset >= 0) {
583                 ret = _dpaa2_flow_rule_move_ipaddr_tail(
584                                 &priv->extract.tc_key_extract[fs_group],
585                                 &flow->fs_rule,
586                                 flow->ipaddr_rule.fs_ipsrc_offset,
587                                 NH_FLD_IP_SRC, prot == NET_PROT_IPV4);
588                 if (ret) {
589                         DPAA2_PMD_ERR("FS src address reorder failed");
590                         return -1;
591                 }
592                 flow->ipaddr_rule.fs_ipsrc_offset =
593                         dpaa2_flow_extract_key_offset(
594                                 &priv->extract.tc_key_extract[fs_group],
595                                 prot, NH_FLD_IP_SRC);
596         }
597         if (flow->ipaddr_rule.fs_ipdst_offset >= 0) {
598                 ret = _dpaa2_flow_rule_move_ipaddr_tail(
599                                 &priv->extract.tc_key_extract[fs_group],
600                                 &flow->fs_rule,
601                                 flow->ipaddr_rule.fs_ipdst_offset,
602                                 NH_FLD_IP_DST, prot == NET_PROT_IPV4);
603                 if (ret) {
604                         DPAA2_PMD_ERR("FS dst address reorder failed");
605                         return -1;
606                 }
607                 flow->ipaddr_rule.fs_ipdst_offset =
608                         dpaa2_flow_extract_key_offset(
609                                 &priv->extract.tc_key_extract[fs_group],
610                                 prot, NH_FLD_IP_DST);
611         }
612
613         return 0;
614 }
615
616 static int
617 dpaa2_flow_extract_support(
618         const uint8_t *mask_src,
619         enum rte_flow_item_type type)
620 {
621         char mask[64];
622         int i, size = 0;
623         const char *mask_support = 0;
624
625         switch (type) {
626         case RTE_FLOW_ITEM_TYPE_ETH:
627                 mask_support = (const char *)&dpaa2_flow_item_eth_mask;
628                 size = sizeof(struct rte_flow_item_eth);
629                 break;
630         case RTE_FLOW_ITEM_TYPE_VLAN:
631                 mask_support = (const char *)&dpaa2_flow_item_vlan_mask;
632                 size = sizeof(struct rte_flow_item_vlan);
633                 break;
634         case RTE_FLOW_ITEM_TYPE_IPV4:
635                 mask_support = (const char *)&dpaa2_flow_item_ipv4_mask;
636                 size = sizeof(struct rte_flow_item_ipv4);
637                 break;
638         case RTE_FLOW_ITEM_TYPE_IPV6:
639                 mask_support = (const char *)&dpaa2_flow_item_ipv6_mask;
640                 size = sizeof(struct rte_flow_item_ipv6);
641                 break;
642         case RTE_FLOW_ITEM_TYPE_ICMP:
643                 mask_support = (const char *)&dpaa2_flow_item_icmp_mask;
644                 size = sizeof(struct rte_flow_item_icmp);
645                 break;
646         case RTE_FLOW_ITEM_TYPE_UDP:
647                 mask_support = (const char *)&dpaa2_flow_item_udp_mask;
648                 size = sizeof(struct rte_flow_item_udp);
649                 break;
650         case RTE_FLOW_ITEM_TYPE_TCP:
651                 mask_support = (const char *)&dpaa2_flow_item_tcp_mask;
652                 size = sizeof(struct rte_flow_item_tcp);
653                 break;
654         case RTE_FLOW_ITEM_TYPE_SCTP:
655                 mask_support = (const char *)&dpaa2_flow_item_sctp_mask;
656                 size = sizeof(struct rte_flow_item_sctp);
657                 break;
658         case RTE_FLOW_ITEM_TYPE_GRE:
659                 mask_support = (const char *)&dpaa2_flow_item_gre_mask;
660                 size = sizeof(struct rte_flow_item_gre);
661                 break;
662         default:
663                 return -1;
664         }
665
666         memcpy(mask, mask_support, size);
667
668         for (i = 0; i < size; i++)
669                 mask[i] = (mask[i] | mask_src[i]);
670
671         if (memcmp(mask, mask_support, size))
672                 return -1;
673
674         return 0;
675 }
676
677 static int
678 dpaa2_configure_flow_eth(struct rte_flow *flow,
679                          struct rte_eth_dev *dev,
680                          const struct rte_flow_attr *attr,
681                          const struct rte_flow_item *pattern,
682                          const struct rte_flow_action actions[] __rte_unused,
683                          struct rte_flow_error *error __rte_unused,
684                          int *device_configured)
685 {
686         int index, ret;
687         int local_cfg = 0;
688         uint32_t group;
689         const struct rte_flow_item_eth *spec, *mask;
690
691         /* TODO: Currently upper bound of range parameter is not implemented */
692         const struct rte_flow_item_eth *last __rte_unused;
693         struct dpaa2_dev_priv *priv = dev->data->dev_private;
694         const char zero_cmp[RTE_ETHER_ADDR_LEN] = {0};
695
696         group = attr->group;
697
698         /* Parse pattern list to get the matching parameters */
699         spec    = (const struct rte_flow_item_eth *)pattern->spec;
700         last    = (const struct rte_flow_item_eth *)pattern->last;
701         mask    = (const struct rte_flow_item_eth *)
702                 (pattern->mask ? pattern->mask : &dpaa2_flow_item_eth_mask);
703         if (!spec) {
704                 /* Don't care any field of eth header,
705                  * only care eth protocol.
706                  */
707                 DPAA2_PMD_WARN("No pattern spec for Eth flow, just skip");
708                 return 0;
709         }
710
711         /* Get traffic class index and flow id to be configured */
712         flow->tc_id = group;
713         flow->tc_index = attr->priority;
714
715         if (dpaa2_flow_extract_support((const uint8_t *)mask,
716                 RTE_FLOW_ITEM_TYPE_ETH)) {
717                 DPAA2_PMD_WARN("Extract field(s) of ethernet not support.");
718
719                 return -1;
720         }
721
722         if (memcmp((const char *)&mask->src, zero_cmp, RTE_ETHER_ADDR_LEN)) {
723                 index = dpaa2_flow_extract_search(
724                                 &priv->extract.qos_key_extract.dpkg,
725                                 NET_PROT_ETH, NH_FLD_ETH_SA);
726                 if (index < 0) {
727                         ret = dpaa2_flow_extract_add(
728                                         &priv->extract.qos_key_extract,
729                                         NET_PROT_ETH, NH_FLD_ETH_SA,
730                                         RTE_ETHER_ADDR_LEN);
731                         if (ret) {
732                                 DPAA2_PMD_ERR("QoS Extract add ETH_SA failed.");
733
734                                 return -1;
735                         }
736                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
737                 }
738                 index = dpaa2_flow_extract_search(
739                                 &priv->extract.tc_key_extract[group].dpkg,
740                                 NET_PROT_ETH, NH_FLD_ETH_SA);
741                 if (index < 0) {
742                         ret = dpaa2_flow_extract_add(
743                                         &priv->extract.tc_key_extract[group],
744                                         NET_PROT_ETH, NH_FLD_ETH_SA,
745                                         RTE_ETHER_ADDR_LEN);
746                         if (ret) {
747                                 DPAA2_PMD_ERR("FS Extract add ETH_SA failed.");
748                                 return -1;
749                         }
750                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
751                 }
752
753                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
754                 if (ret) {
755                         DPAA2_PMD_ERR(
756                                 "Move ipaddr before ETH_SA rule set failed");
757                         return -1;
758                 }
759
760                 ret = dpaa2_flow_rule_data_set(
761                                 &priv->extract.qos_key_extract,
762                                 &flow->qos_rule,
763                                 NET_PROT_ETH,
764                                 NH_FLD_ETH_SA,
765                                 &spec->src.addr_bytes,
766                                 &mask->src.addr_bytes,
767                                 sizeof(struct rte_ether_addr));
768                 if (ret) {
769                         DPAA2_PMD_ERR("QoS NH_FLD_ETH_SA rule data set failed");
770                         return -1;
771                 }
772
773                 ret = dpaa2_flow_rule_data_set(
774                                 &priv->extract.tc_key_extract[group],
775                                 &flow->fs_rule,
776                                 NET_PROT_ETH,
777                                 NH_FLD_ETH_SA,
778                                 &spec->src.addr_bytes,
779                                 &mask->src.addr_bytes,
780                                 sizeof(struct rte_ether_addr));
781                 if (ret) {
782                         DPAA2_PMD_ERR("FS NH_FLD_ETH_SA rule data set failed");
783                         return -1;
784                 }
785         }
786
787         if (memcmp((const char *)&mask->dst, zero_cmp, RTE_ETHER_ADDR_LEN)) {
788                 index = dpaa2_flow_extract_search(
789                                 &priv->extract.qos_key_extract.dpkg,
790                                 NET_PROT_ETH, NH_FLD_ETH_DA);
791                 if (index < 0) {
792                         ret = dpaa2_flow_extract_add(
793                                         &priv->extract.qos_key_extract,
794                                         NET_PROT_ETH, NH_FLD_ETH_DA,
795                                         RTE_ETHER_ADDR_LEN);
796                         if (ret) {
797                                 DPAA2_PMD_ERR("QoS Extract add ETH_DA failed.");
798
799                                 return -1;
800                         }
801                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
802                 }
803
804                 index = dpaa2_flow_extract_search(
805                                 &priv->extract.tc_key_extract[group].dpkg,
806                                 NET_PROT_ETH, NH_FLD_ETH_DA);
807                 if (index < 0) {
808                         ret = dpaa2_flow_extract_add(
809                                         &priv->extract.tc_key_extract[group],
810                                         NET_PROT_ETH, NH_FLD_ETH_DA,
811                                         RTE_ETHER_ADDR_LEN);
812                         if (ret) {
813                                 DPAA2_PMD_ERR("FS Extract add ETH_DA failed.");
814
815                                 return -1;
816                         }
817                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
818                 }
819
820                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
821                 if (ret) {
822                         DPAA2_PMD_ERR(
823                                 "Move ipaddr before ETH DA rule set failed");
824                         return -1;
825                 }
826
827                 ret = dpaa2_flow_rule_data_set(
828                                 &priv->extract.qos_key_extract,
829                                 &flow->qos_rule,
830                                 NET_PROT_ETH,
831                                 NH_FLD_ETH_DA,
832                                 &spec->dst.addr_bytes,
833                                 &mask->dst.addr_bytes,
834                                 sizeof(struct rte_ether_addr));
835                 if (ret) {
836                         DPAA2_PMD_ERR("QoS NH_FLD_ETH_DA rule data set failed");
837                         return -1;
838                 }
839
840                 ret = dpaa2_flow_rule_data_set(
841                                 &priv->extract.tc_key_extract[group],
842                                 &flow->fs_rule,
843                                 NET_PROT_ETH,
844                                 NH_FLD_ETH_DA,
845                                 &spec->dst.addr_bytes,
846                                 &mask->dst.addr_bytes,
847                                 sizeof(struct rte_ether_addr));
848                 if (ret) {
849                         DPAA2_PMD_ERR("FS NH_FLD_ETH_DA rule data set failed");
850                         return -1;
851                 }
852         }
853
854         if (memcmp((const char *)&mask->type, zero_cmp, sizeof(rte_be16_t))) {
855                 index = dpaa2_flow_extract_search(
856                                 &priv->extract.qos_key_extract.dpkg,
857                                 NET_PROT_ETH, NH_FLD_ETH_TYPE);
858                 if (index < 0) {
859                         ret = dpaa2_flow_extract_add(
860                                         &priv->extract.qos_key_extract,
861                                         NET_PROT_ETH, NH_FLD_ETH_TYPE,
862                                         RTE_ETHER_TYPE_LEN);
863                         if (ret) {
864                                 DPAA2_PMD_ERR("QoS Extract add ETH_TYPE failed.");
865
866                                 return -1;
867                         }
868                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
869                 }
870                 index = dpaa2_flow_extract_search(
871                                 &priv->extract.tc_key_extract[group].dpkg,
872                                 NET_PROT_ETH, NH_FLD_ETH_TYPE);
873                 if (index < 0) {
874                         ret = dpaa2_flow_extract_add(
875                                         &priv->extract.tc_key_extract[group],
876                                         NET_PROT_ETH, NH_FLD_ETH_TYPE,
877                                         RTE_ETHER_TYPE_LEN);
878                         if (ret) {
879                                 DPAA2_PMD_ERR("FS Extract add ETH_TYPE failed.");
880
881                                 return -1;
882                         }
883                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
884                 }
885
886                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
887                 if (ret) {
888                         DPAA2_PMD_ERR(
889                                 "Move ipaddr before ETH TYPE rule set failed");
890                                 return -1;
891                 }
892
893                 ret = dpaa2_flow_rule_data_set(
894                                 &priv->extract.qos_key_extract,
895                                 &flow->qos_rule,
896                                 NET_PROT_ETH,
897                                 NH_FLD_ETH_TYPE,
898                                 &spec->type,
899                                 &mask->type,
900                                 sizeof(rte_be16_t));
901                 if (ret) {
902                         DPAA2_PMD_ERR("QoS NH_FLD_ETH_TYPE rule data set failed");
903                         return -1;
904                 }
905
906                 ret = dpaa2_flow_rule_data_set(
907                                 &priv->extract.tc_key_extract[group],
908                                 &flow->fs_rule,
909                                 NET_PROT_ETH,
910                                 NH_FLD_ETH_TYPE,
911                                 &spec->type,
912                                 &mask->type,
913                                 sizeof(rte_be16_t));
914                 if (ret) {
915                         DPAA2_PMD_ERR("FS NH_FLD_ETH_TYPE rule data set failed");
916                         return -1;
917                 }
918         }
919
920         (*device_configured) |= local_cfg;
921
922         return 0;
923 }
924
925 static int
926 dpaa2_configure_flow_vlan(struct rte_flow *flow,
927                           struct rte_eth_dev *dev,
928                           const struct rte_flow_attr *attr,
929                           const struct rte_flow_item *pattern,
930                           const struct rte_flow_action actions[] __rte_unused,
931                           struct rte_flow_error *error __rte_unused,
932                           int *device_configured)
933 {
934         int index, ret;
935         int local_cfg = 0;
936         uint32_t group;
937         const struct rte_flow_item_vlan *spec, *mask;
938
939         const struct rte_flow_item_vlan *last __rte_unused;
940         struct dpaa2_dev_priv *priv = dev->data->dev_private;
941
942         group = attr->group;
943
944         /* Parse pattern list to get the matching parameters */
945         spec    = (const struct rte_flow_item_vlan *)pattern->spec;
946         last    = (const struct rte_flow_item_vlan *)pattern->last;
947         mask    = (const struct rte_flow_item_vlan *)
948                 (pattern->mask ? pattern->mask : &dpaa2_flow_item_vlan_mask);
949
950         /* Get traffic class index and flow id to be configured */
951         flow->tc_id = group;
952         flow->tc_index = attr->priority;
953
954         if (!spec) {
955                 /* Don't care any field of vlan header,
956                  * only care vlan protocol.
957                  */
958                 /* Eth type is actually used for vLan classification.
959                  */
960                 struct proto_discrimination proto;
961
962                 index = dpaa2_flow_extract_search(
963                                 &priv->extract.qos_key_extract.dpkg,
964                                 NET_PROT_ETH, NH_FLD_ETH_TYPE);
965                 if (index < 0) {
966                         ret = dpaa2_flow_proto_discrimination_extract(
967                                                 &priv->extract.qos_key_extract,
968                                                 RTE_FLOW_ITEM_TYPE_ETH);
969                         if (ret) {
970                                 DPAA2_PMD_ERR(
971                                 "QoS Ext ETH_TYPE to discriminate vLan failed");
972
973                                 return -1;
974                         }
975                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
976                 }
977
978                 index = dpaa2_flow_extract_search(
979                                 &priv->extract.tc_key_extract[group].dpkg,
980                                 NET_PROT_ETH, NH_FLD_ETH_TYPE);
981                 if (index < 0) {
982                         ret = dpaa2_flow_proto_discrimination_extract(
983                                         &priv->extract.tc_key_extract[group],
984                                         RTE_FLOW_ITEM_TYPE_ETH);
985                         if (ret) {
986                                 DPAA2_PMD_ERR(
987                                 "FS Ext ETH_TYPE to discriminate vLan failed.");
988
989                                 return -1;
990                         }
991                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
992                 }
993
994                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
995                 if (ret) {
996                         DPAA2_PMD_ERR(
997                         "Move ipaddr before vLan discrimination set failed");
998                         return -1;
999                 }
1000
1001                 proto.type = RTE_FLOW_ITEM_TYPE_ETH;
1002                 proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN);
1003                 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
1004                                                         proto, group);
1005                 if (ret) {
1006                         DPAA2_PMD_ERR("vLan discrimination rule set failed");
1007                         return -1;
1008                 }
1009
1010                 (*device_configured) |= local_cfg;
1011
1012                 return 0;
1013         }
1014
1015         if (dpaa2_flow_extract_support((const uint8_t *)mask,
1016                 RTE_FLOW_ITEM_TYPE_VLAN)) {
1017                 DPAA2_PMD_WARN("Extract field(s) of vlan not support.");
1018
1019                 return -1;
1020         }
1021
1022         if (!mask->tci)
1023                 return 0;
1024
1025         index = dpaa2_flow_extract_search(
1026                                 &priv->extract.qos_key_extract.dpkg,
1027                                 NET_PROT_VLAN, NH_FLD_VLAN_TCI);
1028         if (index < 0) {
1029                 ret = dpaa2_flow_extract_add(
1030                                                 &priv->extract.qos_key_extract,
1031                                                 NET_PROT_VLAN,
1032                                                 NH_FLD_VLAN_TCI,
1033                                                 sizeof(rte_be16_t));
1034                 if (ret) {
1035                         DPAA2_PMD_ERR("QoS Extract add VLAN_TCI failed.");
1036
1037                         return -1;
1038                 }
1039                 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1040         }
1041
1042         index = dpaa2_flow_extract_search(
1043                         &priv->extract.tc_key_extract[group].dpkg,
1044                         NET_PROT_VLAN, NH_FLD_VLAN_TCI);
1045         if (index < 0) {
1046                 ret = dpaa2_flow_extract_add(
1047                                 &priv->extract.tc_key_extract[group],
1048                                 NET_PROT_VLAN,
1049                                 NH_FLD_VLAN_TCI,
1050                                 sizeof(rte_be16_t));
1051                 if (ret) {
1052                         DPAA2_PMD_ERR("FS Extract add VLAN_TCI failed.");
1053
1054                         return -1;
1055                 }
1056                 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1057         }
1058
1059         ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1060         if (ret) {
1061                 DPAA2_PMD_ERR(
1062                         "Move ipaddr before VLAN TCI rule set failed");
1063                 return -1;
1064         }
1065
1066         ret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract,
1067                                 &flow->qos_rule,
1068                                 NET_PROT_VLAN,
1069                                 NH_FLD_VLAN_TCI,
1070                                 &spec->tci,
1071                                 &mask->tci,
1072                                 sizeof(rte_be16_t));
1073         if (ret) {
1074                 DPAA2_PMD_ERR("QoS NH_FLD_VLAN_TCI rule data set failed");
1075                 return -1;
1076         }
1077
1078         ret = dpaa2_flow_rule_data_set(
1079                         &priv->extract.tc_key_extract[group],
1080                         &flow->fs_rule,
1081                         NET_PROT_VLAN,
1082                         NH_FLD_VLAN_TCI,
1083                         &spec->tci,
1084                         &mask->tci,
1085                         sizeof(rte_be16_t));
1086         if (ret) {
1087                 DPAA2_PMD_ERR("FS NH_FLD_VLAN_TCI rule data set failed");
1088                 return -1;
1089         }
1090
1091         (*device_configured) |= local_cfg;
1092
1093         return 0;
1094 }
1095
1096 static int
1097 dpaa2_configure_flow_generic_ip(
1098         struct rte_flow *flow,
1099         struct rte_eth_dev *dev,
1100         const struct rte_flow_attr *attr,
1101         const struct rte_flow_item *pattern,
1102         const struct rte_flow_action actions[] __rte_unused,
1103         struct rte_flow_error *error __rte_unused,
1104         int *device_configured)
1105 {
1106         int index, ret;
1107         int local_cfg = 0;
1108         uint32_t group;
1109         const struct rte_flow_item_ipv4 *spec_ipv4 = 0,
1110                 *mask_ipv4 = 0;
1111         const struct rte_flow_item_ipv6 *spec_ipv6 = 0,
1112                 *mask_ipv6 = 0;
1113         const void *key, *mask;
1114         enum net_prot prot;
1115
1116         struct dpaa2_dev_priv *priv = dev->data->dev_private;
1117         const char zero_cmp[NH_FLD_IPV6_ADDR_SIZE] = {0};
1118         int size;
1119
1120         group = attr->group;
1121
1122         /* Parse pattern list to get the matching parameters */
1123         if (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4) {
1124                 spec_ipv4 = (const struct rte_flow_item_ipv4 *)pattern->spec;
1125                 mask_ipv4 = (const struct rte_flow_item_ipv4 *)
1126                         (pattern->mask ? pattern->mask :
1127                                         &dpaa2_flow_item_ipv4_mask);
1128         } else {
1129                 spec_ipv6 = (const struct rte_flow_item_ipv6 *)pattern->spec;
1130                 mask_ipv6 = (const struct rte_flow_item_ipv6 *)
1131                         (pattern->mask ? pattern->mask :
1132                                         &dpaa2_flow_item_ipv6_mask);
1133         }
1134
1135         /* Get traffic class index and flow id to be configured */
1136         flow->tc_id = group;
1137         flow->tc_index = attr->priority;
1138
1139         if (!spec_ipv4 && !spec_ipv6) {
1140                 /* Don't care any field of IP header,
1141                  * only care IP protocol.
1142                  * Example: flow create 0 ingress pattern ipv6 /
1143                  */
1144                 /* Eth type is actually used for IP identification.
1145                  */
1146                 /* TODO: Current design only supports Eth + IP,
1147                  *  Eth + vLan + IP needs to add.
1148                  */
1149                 struct proto_discrimination proto;
1150
1151                 index = dpaa2_flow_extract_search(
1152                                 &priv->extract.qos_key_extract.dpkg,
1153                                 NET_PROT_ETH, NH_FLD_ETH_TYPE);
1154                 if (index < 0) {
1155                         ret = dpaa2_flow_proto_discrimination_extract(
1156                                         &priv->extract.qos_key_extract,
1157                                         RTE_FLOW_ITEM_TYPE_ETH);
1158                         if (ret) {
1159                                 DPAA2_PMD_ERR(
1160                                 "QoS Ext ETH_TYPE to discriminate IP failed.");
1161
1162                                 return -1;
1163                         }
1164                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1165                 }
1166
1167                 index = dpaa2_flow_extract_search(
1168                                 &priv->extract.tc_key_extract[group].dpkg,
1169                                 NET_PROT_ETH, NH_FLD_ETH_TYPE);
1170                 if (index < 0) {
1171                         ret = dpaa2_flow_proto_discrimination_extract(
1172                                         &priv->extract.tc_key_extract[group],
1173                                         RTE_FLOW_ITEM_TYPE_ETH);
1174                         if (ret) {
1175                                 DPAA2_PMD_ERR(
1176                                 "FS Ext ETH_TYPE to discriminate IP failed");
1177
1178                                 return -1;
1179                         }
1180                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1181                 }
1182
1183                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1184                 if (ret) {
1185                         DPAA2_PMD_ERR(
1186                         "Move ipaddr before IP discrimination set failed");
1187                         return -1;
1188                 }
1189
1190                 proto.type = RTE_FLOW_ITEM_TYPE_ETH;
1191                 if (pattern->type == RTE_FLOW_ITEM_TYPE_IPV4)
1192                         proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
1193                 else
1194                         proto.eth_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
1195                 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
1196                                                         proto, group);
1197                 if (ret) {
1198                         DPAA2_PMD_ERR("IP discrimination rule set failed");
1199                         return -1;
1200                 }
1201
1202                 (*device_configured) |= local_cfg;
1203
1204                 return 0;
1205         }
1206
1207         if (mask_ipv4) {
1208                 if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv4,
1209                         RTE_FLOW_ITEM_TYPE_IPV4)) {
1210                         DPAA2_PMD_WARN("Extract field(s) of IPv4 not support.");
1211
1212                         return -1;
1213                 }
1214         }
1215
1216         if (mask_ipv6) {
1217                 if (dpaa2_flow_extract_support((const uint8_t *)mask_ipv6,
1218                         RTE_FLOW_ITEM_TYPE_IPV6)) {
1219                         DPAA2_PMD_WARN("Extract field(s) of IPv6 not support.");
1220
1221                         return -1;
1222                 }
1223         }
1224
1225         if (mask_ipv4 && (mask_ipv4->hdr.src_addr ||
1226                 mask_ipv4->hdr.dst_addr)) {
1227                 flow->ipaddr_rule.ipaddr_type = FLOW_IPV4_ADDR;
1228         } else if (mask_ipv6 &&
1229                 (memcmp((const char *)mask_ipv6->hdr.src_addr,
1230                                 zero_cmp, NH_FLD_IPV6_ADDR_SIZE) ||
1231                 memcmp((const char *)mask_ipv6->hdr.dst_addr,
1232                                 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
1233                 flow->ipaddr_rule.ipaddr_type = FLOW_IPV6_ADDR;
1234         }
1235
1236         if ((mask_ipv4 && mask_ipv4->hdr.src_addr) ||
1237                 (mask_ipv6 &&
1238                         memcmp((const char *)mask_ipv6->hdr.src_addr,
1239                                 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
1240                 index = dpaa2_flow_extract_search(
1241                                 &priv->extract.qos_key_extract.dpkg,
1242                                 NET_PROT_IP, NH_FLD_IP_SRC);
1243                 if (index < 0) {
1244                         ret = dpaa2_flow_extract_add(
1245                                                 &priv->extract.qos_key_extract,
1246                                                 NET_PROT_IP,
1247                                                 NH_FLD_IP_SRC,
1248                                                 0);
1249                         if (ret) {
1250                                 DPAA2_PMD_ERR("QoS Extract add IP_SRC failed.");
1251
1252                                 return -1;
1253                         }
1254                         local_cfg |= (DPAA2_QOS_TABLE_RECONFIGURE |
1255                                 DPAA2_QOS_TABLE_IPADDR_EXTRACT);
1256                 }
1257
1258                 index = dpaa2_flow_extract_search(
1259                                 &priv->extract.tc_key_extract[group].dpkg,
1260                                 NET_PROT_IP, NH_FLD_IP_SRC);
1261                 if (index < 0) {
1262                         ret = dpaa2_flow_extract_add(
1263                                         &priv->extract.tc_key_extract[group],
1264                                         NET_PROT_IP,
1265                                         NH_FLD_IP_SRC,
1266                                         0);
1267                         if (ret) {
1268                                 DPAA2_PMD_ERR("FS Extract add IP_SRC failed.");
1269
1270                                 return -1;
1271                         }
1272                         local_cfg |= (DPAA2_FS_TABLE_RECONFIGURE |
1273                                 DPAA2_FS_TABLE_IPADDR_EXTRACT);
1274                 }
1275
1276                 if (spec_ipv4)
1277                         key = &spec_ipv4->hdr.src_addr;
1278                 else
1279                         key = &spec_ipv6->hdr.src_addr[0];
1280                 if (mask_ipv4) {
1281                         mask = &mask_ipv4->hdr.src_addr;
1282                         size = NH_FLD_IPV4_ADDR_SIZE;
1283                         prot = NET_PROT_IPV4;
1284                 } else {
1285                         mask = &mask_ipv6->hdr.src_addr[0];
1286                         size = NH_FLD_IPV6_ADDR_SIZE;
1287                         prot = NET_PROT_IPV6;
1288                 }
1289
1290                 ret = dpaa2_flow_rule_data_set(
1291                                 &priv->extract.qos_key_extract,
1292                                 &flow->qos_rule,
1293                                 prot, NH_FLD_IP_SRC,
1294                                 key,    mask, size);
1295                 if (ret) {
1296                         DPAA2_PMD_ERR("QoS NH_FLD_IP_SRC rule data set failed");
1297                         return -1;
1298                 }
1299
1300                 ret = dpaa2_flow_rule_data_set(
1301                                 &priv->extract.tc_key_extract[group],
1302                                 &flow->fs_rule,
1303                                 prot, NH_FLD_IP_SRC,
1304                                 key,    mask, size);
1305                 if (ret) {
1306                         DPAA2_PMD_ERR("FS NH_FLD_IP_SRC rule data set failed");
1307                         return -1;
1308                 }
1309
1310                 flow->ipaddr_rule.qos_ipsrc_offset =
1311                         dpaa2_flow_extract_key_offset(
1312                                 &priv->extract.qos_key_extract,
1313                                 prot, NH_FLD_IP_SRC);
1314                 flow->ipaddr_rule.fs_ipsrc_offset =
1315                         dpaa2_flow_extract_key_offset(
1316                                 &priv->extract.tc_key_extract[group],
1317                                 prot, NH_FLD_IP_SRC);
1318         }
1319
1320         if ((mask_ipv4 && mask_ipv4->hdr.dst_addr) ||
1321                 (mask_ipv6 &&
1322                         memcmp((const char *)mask_ipv6->hdr.dst_addr,
1323                                 zero_cmp, NH_FLD_IPV6_ADDR_SIZE))) {
1324                 index = dpaa2_flow_extract_search(
1325                                 &priv->extract.qos_key_extract.dpkg,
1326                                 NET_PROT_IP, NH_FLD_IP_DST);
1327                 if (index < 0) {
1328                         if (mask_ipv4)
1329                                 size = NH_FLD_IPV4_ADDR_SIZE;
1330                         else
1331                                 size = NH_FLD_IPV6_ADDR_SIZE;
1332                         ret = dpaa2_flow_extract_add(
1333                                                 &priv->extract.qos_key_extract,
1334                                                 NET_PROT_IP,
1335                                                 NH_FLD_IP_DST,
1336                                                 size);
1337                         if (ret) {
1338                                 DPAA2_PMD_ERR("QoS Extract add IP_DST failed.");
1339
1340                                 return -1;
1341                         }
1342                         local_cfg |= (DPAA2_QOS_TABLE_RECONFIGURE |
1343                                 DPAA2_QOS_TABLE_IPADDR_EXTRACT);
1344                 }
1345
1346                 index = dpaa2_flow_extract_search(
1347                                 &priv->extract.tc_key_extract[group].dpkg,
1348                                 NET_PROT_IP, NH_FLD_IP_DST);
1349                 if (index < 0) {
1350                         if (mask_ipv4)
1351                                 size = NH_FLD_IPV4_ADDR_SIZE;
1352                         else
1353                                 size = NH_FLD_IPV6_ADDR_SIZE;
1354                         ret = dpaa2_flow_extract_add(
1355                                         &priv->extract.tc_key_extract[group],
1356                                         NET_PROT_IP,
1357                                         NH_FLD_IP_DST,
1358                                         size);
1359                         if (ret) {
1360                                 DPAA2_PMD_ERR("FS Extract add IP_DST failed.");
1361
1362                                 return -1;
1363                         }
1364                         local_cfg |= (DPAA2_FS_TABLE_RECONFIGURE |
1365                                 DPAA2_FS_TABLE_IPADDR_EXTRACT);
1366                 }
1367
1368                 if (spec_ipv4)
1369                         key = &spec_ipv4->hdr.dst_addr;
1370                 else
1371                         key = spec_ipv6->hdr.dst_addr;
1372                 if (mask_ipv4) {
1373                         mask = &mask_ipv4->hdr.dst_addr;
1374                         size = NH_FLD_IPV4_ADDR_SIZE;
1375                         prot = NET_PROT_IPV4;
1376                 } else {
1377                         mask = &mask_ipv6->hdr.dst_addr[0];
1378                         size = NH_FLD_IPV6_ADDR_SIZE;
1379                         prot = NET_PROT_IPV6;
1380                 }
1381
1382                 ret = dpaa2_flow_rule_data_set(
1383                                 &priv->extract.qos_key_extract,
1384                                 &flow->qos_rule,
1385                                 prot, NH_FLD_IP_DST,
1386                                 key,    mask, size);
1387                 if (ret) {
1388                         DPAA2_PMD_ERR("QoS NH_FLD_IP_DST rule data set failed");
1389                         return -1;
1390                 }
1391
1392                 ret = dpaa2_flow_rule_data_set(
1393                                 &priv->extract.tc_key_extract[group],
1394                                 &flow->fs_rule,
1395                                 prot, NH_FLD_IP_DST,
1396                                 key,    mask, size);
1397                 if (ret) {
1398                         DPAA2_PMD_ERR("FS NH_FLD_IP_DST rule data set failed");
1399                         return -1;
1400                 }
1401                 flow->ipaddr_rule.qos_ipdst_offset =
1402                         dpaa2_flow_extract_key_offset(
1403                                 &priv->extract.qos_key_extract,
1404                                 prot, NH_FLD_IP_DST);
1405                 flow->ipaddr_rule.fs_ipdst_offset =
1406                         dpaa2_flow_extract_key_offset(
1407                                 &priv->extract.tc_key_extract[group],
1408                                 prot, NH_FLD_IP_DST);
1409         }
1410
1411         if ((mask_ipv4 && mask_ipv4->hdr.next_proto_id) ||
1412                 (mask_ipv6 && mask_ipv6->hdr.proto)) {
1413                 index = dpaa2_flow_extract_search(
1414                                 &priv->extract.qos_key_extract.dpkg,
1415                                 NET_PROT_IP, NH_FLD_IP_PROTO);
1416                 if (index < 0) {
1417                         ret = dpaa2_flow_extract_add(
1418                                 &priv->extract.qos_key_extract,
1419                                 NET_PROT_IP,
1420                                 NH_FLD_IP_PROTO,
1421                                 NH_FLD_IP_PROTO_SIZE);
1422                         if (ret) {
1423                                 DPAA2_PMD_ERR("QoS Extract add IP_DST failed.");
1424
1425                                 return -1;
1426                         }
1427                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1428                 }
1429
1430                 index = dpaa2_flow_extract_search(
1431                                 &priv->extract.tc_key_extract[group].dpkg,
1432                                 NET_PROT_IP, NH_FLD_IP_PROTO);
1433                 if (index < 0) {
1434                         ret = dpaa2_flow_extract_add(
1435                                         &priv->extract.tc_key_extract[group],
1436                                         NET_PROT_IP,
1437                                         NH_FLD_IP_PROTO,
1438                                         NH_FLD_IP_PROTO_SIZE);
1439                         if (ret) {
1440                                 DPAA2_PMD_ERR("FS Extract add IP_DST failed.");
1441
1442                                 return -1;
1443                         }
1444                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1445                 }
1446
1447                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1448                 if (ret) {
1449                         DPAA2_PMD_ERR(
1450                                 "Move ipaddr after NH_FLD_IP_PROTO rule set failed");
1451                         return -1;
1452                 }
1453
1454                 if (spec_ipv4)
1455                         key = &spec_ipv4->hdr.next_proto_id;
1456                 else
1457                         key = &spec_ipv6->hdr.proto;
1458                 if (mask_ipv4)
1459                         mask = &mask_ipv4->hdr.next_proto_id;
1460                 else
1461                         mask = &mask_ipv6->hdr.proto;
1462
1463                 ret = dpaa2_flow_rule_data_set(
1464                                 &priv->extract.qos_key_extract,
1465                                 &flow->qos_rule,
1466                                 NET_PROT_IP,
1467                                 NH_FLD_IP_PROTO,
1468                                 key,    mask, NH_FLD_IP_PROTO_SIZE);
1469                 if (ret) {
1470                         DPAA2_PMD_ERR("QoS NH_FLD_IP_PROTO rule data set failed");
1471                         return -1;
1472                 }
1473
1474                 ret = dpaa2_flow_rule_data_set(
1475                                 &priv->extract.tc_key_extract[group],
1476                                 &flow->fs_rule,
1477                                 NET_PROT_IP,
1478                                 NH_FLD_IP_PROTO,
1479                                 key,    mask, NH_FLD_IP_PROTO_SIZE);
1480                 if (ret) {
1481                         DPAA2_PMD_ERR("FS NH_FLD_IP_PROTO rule data set failed");
1482                         return -1;
1483                 }
1484         }
1485
1486         (*device_configured) |= local_cfg;
1487
1488         return 0;
1489 }
1490
1491 static int
1492 dpaa2_configure_flow_icmp(struct rte_flow *flow,
1493                           struct rte_eth_dev *dev,
1494                           const struct rte_flow_attr *attr,
1495                           const struct rte_flow_item *pattern,
1496                           const struct rte_flow_action actions[] __rte_unused,
1497                           struct rte_flow_error *error __rte_unused,
1498                           int *device_configured)
1499 {
1500         int index, ret;
1501         int local_cfg = 0;
1502         uint32_t group;
1503         const struct rte_flow_item_icmp *spec, *mask;
1504
1505         const struct rte_flow_item_icmp *last __rte_unused;
1506         struct dpaa2_dev_priv *priv = dev->data->dev_private;
1507
1508         group = attr->group;
1509
1510         /* Parse pattern list to get the matching parameters */
1511         spec    = (const struct rte_flow_item_icmp *)pattern->spec;
1512         last    = (const struct rte_flow_item_icmp *)pattern->last;
1513         mask    = (const struct rte_flow_item_icmp *)
1514                 (pattern->mask ? pattern->mask : &dpaa2_flow_item_icmp_mask);
1515
1516         /* Get traffic class index and flow id to be configured */
1517         flow->tc_id = group;
1518         flow->tc_index = attr->priority;
1519
1520         if (!spec) {
1521                 /* Don't care any field of ICMP header,
1522                  * only care ICMP protocol.
1523                  * Example: flow create 0 ingress pattern icmp /
1524                  */
1525                 /* Next proto of Generical IP is actually used
1526                  * for ICMP identification.
1527                  */
1528                 struct proto_discrimination proto;
1529
1530                 index = dpaa2_flow_extract_search(
1531                                 &priv->extract.qos_key_extract.dpkg,
1532                                 NET_PROT_IP, NH_FLD_IP_PROTO);
1533                 if (index < 0) {
1534                         ret = dpaa2_flow_proto_discrimination_extract(
1535                                         &priv->extract.qos_key_extract,
1536                                         DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
1537                         if (ret) {
1538                                 DPAA2_PMD_ERR(
1539                                         "QoS Extract IP protocol to discriminate ICMP failed.");
1540
1541                                 return -1;
1542                         }
1543                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1544                 }
1545
1546                 index = dpaa2_flow_extract_search(
1547                                 &priv->extract.tc_key_extract[group].dpkg,
1548                                 NET_PROT_IP, NH_FLD_IP_PROTO);
1549                 if (index < 0) {
1550                         ret = dpaa2_flow_proto_discrimination_extract(
1551                                         &priv->extract.tc_key_extract[group],
1552                                         DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
1553                         if (ret) {
1554                                 DPAA2_PMD_ERR(
1555                                         "FS Extract IP protocol to discriminate ICMP failed.");
1556
1557                                 return -1;
1558                         }
1559                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1560                 }
1561
1562                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1563                 if (ret) {
1564                         DPAA2_PMD_ERR(
1565                                 "Move IP addr before ICMP discrimination set failed");
1566                         return -1;
1567                 }
1568
1569                 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
1570                 proto.ip_proto = IPPROTO_ICMP;
1571                 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
1572                                                         proto, group);
1573                 if (ret) {
1574                         DPAA2_PMD_ERR("ICMP discrimination rule set failed");
1575                         return -1;
1576                 }
1577
1578                 (*device_configured) |= local_cfg;
1579
1580                 return 0;
1581         }
1582
1583         if (dpaa2_flow_extract_support((const uint8_t *)mask,
1584                 RTE_FLOW_ITEM_TYPE_ICMP)) {
1585                 DPAA2_PMD_WARN("Extract field(s) of ICMP not support.");
1586
1587                 return -1;
1588         }
1589
1590         if (mask->hdr.icmp_type) {
1591                 index = dpaa2_flow_extract_search(
1592                                 &priv->extract.qos_key_extract.dpkg,
1593                                 NET_PROT_ICMP, NH_FLD_ICMP_TYPE);
1594                 if (index < 0) {
1595                         ret = dpaa2_flow_extract_add(
1596                                         &priv->extract.qos_key_extract,
1597                                         NET_PROT_ICMP,
1598                                         NH_FLD_ICMP_TYPE,
1599                                         NH_FLD_ICMP_TYPE_SIZE);
1600                         if (ret) {
1601                                 DPAA2_PMD_ERR("QoS Extract add ICMP_TYPE failed.");
1602
1603                                 return -1;
1604                         }
1605                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1606                 }
1607
1608                 index = dpaa2_flow_extract_search(
1609                                 &priv->extract.tc_key_extract[group].dpkg,
1610                                 NET_PROT_ICMP, NH_FLD_ICMP_TYPE);
1611                 if (index < 0) {
1612                         ret = dpaa2_flow_extract_add(
1613                                         &priv->extract.tc_key_extract[group],
1614                                         NET_PROT_ICMP,
1615                                         NH_FLD_ICMP_TYPE,
1616                                         NH_FLD_ICMP_TYPE_SIZE);
1617                         if (ret) {
1618                                 DPAA2_PMD_ERR("FS Extract add ICMP_TYPE failed.");
1619
1620                                 return -1;
1621                         }
1622                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1623                 }
1624
1625                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1626                 if (ret) {
1627                         DPAA2_PMD_ERR(
1628                                 "Move ipaddr before ICMP TYPE set failed");
1629                         return -1;
1630                 }
1631
1632                 ret = dpaa2_flow_rule_data_set(
1633                                 &priv->extract.qos_key_extract,
1634                                 &flow->qos_rule,
1635                                 NET_PROT_ICMP,
1636                                 NH_FLD_ICMP_TYPE,
1637                                 &spec->hdr.icmp_type,
1638                                 &mask->hdr.icmp_type,
1639                                 NH_FLD_ICMP_TYPE_SIZE);
1640                 if (ret) {
1641                         DPAA2_PMD_ERR("QoS NH_FLD_ICMP_TYPE rule data set failed");
1642                         return -1;
1643                 }
1644
1645                 ret = dpaa2_flow_rule_data_set(
1646                                 &priv->extract.tc_key_extract[group],
1647                                 &flow->fs_rule,
1648                                 NET_PROT_ICMP,
1649                                 NH_FLD_ICMP_TYPE,
1650                                 &spec->hdr.icmp_type,
1651                                 &mask->hdr.icmp_type,
1652                                 NH_FLD_ICMP_TYPE_SIZE);
1653                 if (ret) {
1654                         DPAA2_PMD_ERR("FS NH_FLD_ICMP_TYPE rule data set failed");
1655                         return -1;
1656                 }
1657         }
1658
1659         if (mask->hdr.icmp_code) {
1660                 index = dpaa2_flow_extract_search(
1661                                 &priv->extract.qos_key_extract.dpkg,
1662                                 NET_PROT_ICMP, NH_FLD_ICMP_CODE);
1663                 if (index < 0) {
1664                         ret = dpaa2_flow_extract_add(
1665                                         &priv->extract.qos_key_extract,
1666                                         NET_PROT_ICMP,
1667                                         NH_FLD_ICMP_CODE,
1668                                         NH_FLD_ICMP_CODE_SIZE);
1669                         if (ret) {
1670                                 DPAA2_PMD_ERR("QoS Extract add ICMP_CODE failed.");
1671
1672                                 return -1;
1673                         }
1674                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1675                 }
1676
1677                 index = dpaa2_flow_extract_search(
1678                                 &priv->extract.tc_key_extract[group].dpkg,
1679                                 NET_PROT_ICMP, NH_FLD_ICMP_CODE);
1680                 if (index < 0) {
1681                         ret = dpaa2_flow_extract_add(
1682                                         &priv->extract.tc_key_extract[group],
1683                                         NET_PROT_ICMP,
1684                                         NH_FLD_ICMP_CODE,
1685                                         NH_FLD_ICMP_CODE_SIZE);
1686                         if (ret) {
1687                                 DPAA2_PMD_ERR("FS Extract add ICMP_CODE failed.");
1688
1689                                 return -1;
1690                         }
1691                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1692                 }
1693
1694                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1695                 if (ret) {
1696                         DPAA2_PMD_ERR(
1697                                 "Move ipaddr after ICMP CODE set failed");
1698                         return -1;
1699                 }
1700
1701                 ret = dpaa2_flow_rule_data_set(
1702                                 &priv->extract.qos_key_extract,
1703                                 &flow->qos_rule,
1704                                 NET_PROT_ICMP,
1705                                 NH_FLD_ICMP_CODE,
1706                                 &spec->hdr.icmp_code,
1707                                 &mask->hdr.icmp_code,
1708                                 NH_FLD_ICMP_CODE_SIZE);
1709                 if (ret) {
1710                         DPAA2_PMD_ERR("QoS NH_FLD_ICMP_CODE rule data set failed");
1711                         return -1;
1712                 }
1713
1714                 ret = dpaa2_flow_rule_data_set(
1715                                 &priv->extract.tc_key_extract[group],
1716                                 &flow->fs_rule,
1717                                 NET_PROT_ICMP,
1718                                 NH_FLD_ICMP_CODE,
1719                                 &spec->hdr.icmp_code,
1720                                 &mask->hdr.icmp_code,
1721                                 NH_FLD_ICMP_CODE_SIZE);
1722                 if (ret) {
1723                         DPAA2_PMD_ERR("FS NH_FLD_ICMP_CODE rule data set failed");
1724                         return -1;
1725                 }
1726         }
1727
1728         (*device_configured) |= local_cfg;
1729
1730         return 0;
1731 }
1732
1733 static int
1734 dpaa2_configure_flow_udp(struct rte_flow *flow,
1735                          struct rte_eth_dev *dev,
1736                           const struct rte_flow_attr *attr,
1737                           const struct rte_flow_item *pattern,
1738                           const struct rte_flow_action actions[] __rte_unused,
1739                           struct rte_flow_error *error __rte_unused,
1740                           int *device_configured)
1741 {
1742         int index, ret;
1743         int local_cfg = 0;
1744         uint32_t group;
1745         const struct rte_flow_item_udp *spec, *mask;
1746
1747         const struct rte_flow_item_udp *last __rte_unused;
1748         struct dpaa2_dev_priv *priv = dev->data->dev_private;
1749
1750         group = attr->group;
1751
1752         /* Parse pattern list to get the matching parameters */
1753         spec    = (const struct rte_flow_item_udp *)pattern->spec;
1754         last    = (const struct rte_flow_item_udp *)pattern->last;
1755         mask    = (const struct rte_flow_item_udp *)
1756                 (pattern->mask ? pattern->mask : &dpaa2_flow_item_udp_mask);
1757
1758         /* Get traffic class index and flow id to be configured */
1759         flow->tc_id = group;
1760         flow->tc_index = attr->priority;
1761
1762         if (!spec || !mc_l4_port_identification) {
1763                 struct proto_discrimination proto;
1764
1765                 index = dpaa2_flow_extract_search(
1766                                 &priv->extract.qos_key_extract.dpkg,
1767                                 NET_PROT_IP, NH_FLD_IP_PROTO);
1768                 if (index < 0) {
1769                         ret = dpaa2_flow_proto_discrimination_extract(
1770                                         &priv->extract.qos_key_extract,
1771                                         DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
1772                         if (ret) {
1773                                 DPAA2_PMD_ERR(
1774                                         "QoS Extract IP protocol to discriminate UDP failed.");
1775
1776                                 return -1;
1777                         }
1778                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1779                 }
1780
1781                 index = dpaa2_flow_extract_search(
1782                                 &priv->extract.tc_key_extract[group].dpkg,
1783                                 NET_PROT_IP, NH_FLD_IP_PROTO);
1784                 if (index < 0) {
1785                         ret = dpaa2_flow_proto_discrimination_extract(
1786                                 &priv->extract.tc_key_extract[group],
1787                                 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
1788                         if (ret) {
1789                                 DPAA2_PMD_ERR(
1790                                         "FS Extract IP protocol to discriminate UDP failed.");
1791
1792                                 return -1;
1793                         }
1794                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1795                 }
1796
1797                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1798                 if (ret) {
1799                         DPAA2_PMD_ERR(
1800                                 "Move IP addr before UDP discrimination set failed");
1801                         return -1;
1802                 }
1803
1804                 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
1805                 proto.ip_proto = IPPROTO_UDP;
1806                 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
1807                                                         proto, group);
1808                 if (ret) {
1809                         DPAA2_PMD_ERR("UDP discrimination rule set failed");
1810                         return -1;
1811                 }
1812
1813                 (*device_configured) |= local_cfg;
1814
1815                 if (!spec)
1816                         return 0;
1817         }
1818
1819         if (dpaa2_flow_extract_support((const uint8_t *)mask,
1820                 RTE_FLOW_ITEM_TYPE_UDP)) {
1821                 DPAA2_PMD_WARN("Extract field(s) of UDP not support.");
1822
1823                 return -1;
1824         }
1825
1826         if (mask->hdr.src_port) {
1827                 index = dpaa2_flow_extract_search(
1828                                 &priv->extract.qos_key_extract.dpkg,
1829                                 NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
1830                 if (index < 0) {
1831                         ret = dpaa2_flow_extract_add(
1832                                         &priv->extract.qos_key_extract,
1833                                 NET_PROT_UDP,
1834                                 NH_FLD_UDP_PORT_SRC,
1835                                 NH_FLD_UDP_PORT_SIZE);
1836                         if (ret) {
1837                                 DPAA2_PMD_ERR("QoS Extract add UDP_SRC failed.");
1838
1839                                 return -1;
1840                         }
1841                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1842                 }
1843
1844                 index = dpaa2_flow_extract_search(
1845                                 &priv->extract.tc_key_extract[group].dpkg,
1846                                 NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
1847                 if (index < 0) {
1848                         ret = dpaa2_flow_extract_add(
1849                                         &priv->extract.tc_key_extract[group],
1850                                         NET_PROT_UDP,
1851                                         NH_FLD_UDP_PORT_SRC,
1852                                         NH_FLD_UDP_PORT_SIZE);
1853                         if (ret) {
1854                                 DPAA2_PMD_ERR("FS Extract add UDP_SRC failed.");
1855
1856                                 return -1;
1857                         }
1858                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1859                 }
1860
1861                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1862                 if (ret) {
1863                         DPAA2_PMD_ERR(
1864                                 "Move ipaddr before UDP_PORT_SRC set failed");
1865                         return -1;
1866                 }
1867
1868                 ret = dpaa2_flow_rule_data_set(&priv->extract.qos_key_extract,
1869                                 &flow->qos_rule,
1870                                 NET_PROT_UDP,
1871                                 NH_FLD_UDP_PORT_SRC,
1872                                 &spec->hdr.src_port,
1873                                 &mask->hdr.src_port,
1874                                 NH_FLD_UDP_PORT_SIZE);
1875                 if (ret) {
1876                         DPAA2_PMD_ERR(
1877                                 "QoS NH_FLD_UDP_PORT_SRC rule data set failed");
1878                         return -1;
1879                 }
1880
1881                 ret = dpaa2_flow_rule_data_set(
1882                                 &priv->extract.tc_key_extract[group],
1883                                 &flow->fs_rule,
1884                                 NET_PROT_UDP,
1885                                 NH_FLD_UDP_PORT_SRC,
1886                                 &spec->hdr.src_port,
1887                                 &mask->hdr.src_port,
1888                                 NH_FLD_UDP_PORT_SIZE);
1889                 if (ret) {
1890                         DPAA2_PMD_ERR(
1891                                 "FS NH_FLD_UDP_PORT_SRC rule data set failed");
1892                         return -1;
1893                 }
1894         }
1895
1896         if (mask->hdr.dst_port) {
1897                 index = dpaa2_flow_extract_search(
1898                                 &priv->extract.qos_key_extract.dpkg,
1899                                 NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
1900                 if (index < 0) {
1901                         ret = dpaa2_flow_extract_add(
1902                                         &priv->extract.qos_key_extract,
1903                                         NET_PROT_UDP,
1904                                         NH_FLD_UDP_PORT_DST,
1905                                         NH_FLD_UDP_PORT_SIZE);
1906                         if (ret) {
1907                                 DPAA2_PMD_ERR("QoS Extract add UDP_DST failed.");
1908
1909                                 return -1;
1910                         }
1911                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
1912                 }
1913
1914                 index = dpaa2_flow_extract_search(
1915                                 &priv->extract.tc_key_extract[group].dpkg,
1916                                 NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
1917                 if (index < 0) {
1918                         ret = dpaa2_flow_extract_add(
1919                                         &priv->extract.tc_key_extract[group],
1920                                         NET_PROT_UDP,
1921                                         NH_FLD_UDP_PORT_DST,
1922                                         NH_FLD_UDP_PORT_SIZE);
1923                         if (ret) {
1924                                 DPAA2_PMD_ERR("FS Extract add UDP_DST failed.");
1925
1926                                 return -1;
1927                         }
1928                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
1929                 }
1930
1931                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
1932                 if (ret) {
1933                         DPAA2_PMD_ERR(
1934                                 "Move ipaddr before UDP_PORT_DST set failed");
1935                         return -1;
1936                 }
1937
1938                 ret = dpaa2_flow_rule_data_set(
1939                                 &priv->extract.qos_key_extract,
1940                                 &flow->qos_rule,
1941                                 NET_PROT_UDP,
1942                                 NH_FLD_UDP_PORT_DST,
1943                                 &spec->hdr.dst_port,
1944                                 &mask->hdr.dst_port,
1945                                 NH_FLD_UDP_PORT_SIZE);
1946                 if (ret) {
1947                         DPAA2_PMD_ERR(
1948                                 "QoS NH_FLD_UDP_PORT_DST rule data set failed");
1949                         return -1;
1950                 }
1951
1952                 ret = dpaa2_flow_rule_data_set(
1953                                 &priv->extract.tc_key_extract[group],
1954                                 &flow->fs_rule,
1955                                 NET_PROT_UDP,
1956                                 NH_FLD_UDP_PORT_DST,
1957                                 &spec->hdr.dst_port,
1958                                 &mask->hdr.dst_port,
1959                                 NH_FLD_UDP_PORT_SIZE);
1960                 if (ret) {
1961                         DPAA2_PMD_ERR(
1962                                 "FS NH_FLD_UDP_PORT_DST rule data set failed");
1963                         return -1;
1964                 }
1965         }
1966
1967         (*device_configured) |= local_cfg;
1968
1969         return 0;
1970 }
1971
1972 static int
1973 dpaa2_configure_flow_tcp(struct rte_flow *flow,
1974                          struct rte_eth_dev *dev,
1975                          const struct rte_flow_attr *attr,
1976                          const struct rte_flow_item *pattern,
1977                          const struct rte_flow_action actions[] __rte_unused,
1978                          struct rte_flow_error *error __rte_unused,
1979                          int *device_configured)
1980 {
1981         int index, ret;
1982         int local_cfg = 0;
1983         uint32_t group;
1984         const struct rte_flow_item_tcp *spec, *mask;
1985
1986         const struct rte_flow_item_tcp *last __rte_unused;
1987         struct dpaa2_dev_priv *priv = dev->data->dev_private;
1988
1989         group = attr->group;
1990
1991         /* Parse pattern list to get the matching parameters */
1992         spec    = (const struct rte_flow_item_tcp *)pattern->spec;
1993         last    = (const struct rte_flow_item_tcp *)pattern->last;
1994         mask    = (const struct rte_flow_item_tcp *)
1995                 (pattern->mask ? pattern->mask : &dpaa2_flow_item_tcp_mask);
1996
1997         /* Get traffic class index and flow id to be configured */
1998         flow->tc_id = group;
1999         flow->tc_index = attr->priority;
2000
2001         if (!spec || !mc_l4_port_identification) {
2002                 struct proto_discrimination proto;
2003
2004                 index = dpaa2_flow_extract_search(
2005                                 &priv->extract.qos_key_extract.dpkg,
2006                                 NET_PROT_IP, NH_FLD_IP_PROTO);
2007                 if (index < 0) {
2008                         ret = dpaa2_flow_proto_discrimination_extract(
2009                                         &priv->extract.qos_key_extract,
2010                                         DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2011                         if (ret) {
2012                                 DPAA2_PMD_ERR(
2013                                         "QoS Extract IP protocol to discriminate TCP failed.");
2014
2015                                 return -1;
2016                         }
2017                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2018                 }
2019
2020                 index = dpaa2_flow_extract_search(
2021                                 &priv->extract.tc_key_extract[group].dpkg,
2022                                 NET_PROT_IP, NH_FLD_IP_PROTO);
2023                 if (index < 0) {
2024                         ret = dpaa2_flow_proto_discrimination_extract(
2025                                 &priv->extract.tc_key_extract[group],
2026                                 DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2027                         if (ret) {
2028                                 DPAA2_PMD_ERR(
2029                                         "FS Extract IP protocol to discriminate TCP failed.");
2030
2031                                 return -1;
2032                         }
2033                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2034                 }
2035
2036                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2037                 if (ret) {
2038                         DPAA2_PMD_ERR(
2039                                 "Move IP addr before TCP discrimination set failed");
2040                         return -1;
2041                 }
2042
2043                 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
2044                 proto.ip_proto = IPPROTO_TCP;
2045                 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
2046                                                         proto, group);
2047                 if (ret) {
2048                         DPAA2_PMD_ERR("TCP discrimination rule set failed");
2049                         return -1;
2050                 }
2051
2052                 (*device_configured) |= local_cfg;
2053
2054                 if (!spec)
2055                         return 0;
2056         }
2057
2058         if (dpaa2_flow_extract_support((const uint8_t *)mask,
2059                 RTE_FLOW_ITEM_TYPE_TCP)) {
2060                 DPAA2_PMD_WARN("Extract field(s) of TCP not support.");
2061
2062                 return -1;
2063         }
2064
2065         if (mask->hdr.src_port) {
2066                 index = dpaa2_flow_extract_search(
2067                                 &priv->extract.qos_key_extract.dpkg,
2068                                 NET_PROT_TCP, NH_FLD_TCP_PORT_SRC);
2069                 if (index < 0) {
2070                         ret = dpaa2_flow_extract_add(
2071                                         &priv->extract.qos_key_extract,
2072                                         NET_PROT_TCP,
2073                                         NH_FLD_TCP_PORT_SRC,
2074                                         NH_FLD_TCP_PORT_SIZE);
2075                         if (ret) {
2076                                 DPAA2_PMD_ERR("QoS Extract add TCP_SRC failed.");
2077
2078                                 return -1;
2079                         }
2080                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2081                 }
2082
2083                 index = dpaa2_flow_extract_search(
2084                                 &priv->extract.tc_key_extract[group].dpkg,
2085                                 NET_PROT_TCP, NH_FLD_TCP_PORT_SRC);
2086                 if (index < 0) {
2087                         ret = dpaa2_flow_extract_add(
2088                                         &priv->extract.tc_key_extract[group],
2089                                         NET_PROT_TCP,
2090                                         NH_FLD_TCP_PORT_SRC,
2091                                         NH_FLD_TCP_PORT_SIZE);
2092                         if (ret) {
2093                                 DPAA2_PMD_ERR("FS Extract add TCP_SRC failed.");
2094
2095                                 return -1;
2096                         }
2097                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2098                 }
2099
2100                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2101                 if (ret) {
2102                         DPAA2_PMD_ERR(
2103                                 "Move ipaddr before TCP_PORT_SRC set failed");
2104                         return -1;
2105                 }
2106
2107                 ret = dpaa2_flow_rule_data_set(
2108                                 &priv->extract.qos_key_extract,
2109                                 &flow->qos_rule,
2110                                 NET_PROT_TCP,
2111                                 NH_FLD_TCP_PORT_SRC,
2112                                 &spec->hdr.src_port,
2113                                 &mask->hdr.src_port,
2114                                 NH_FLD_TCP_PORT_SIZE);
2115                 if (ret) {
2116                         DPAA2_PMD_ERR(
2117                                 "QoS NH_FLD_TCP_PORT_SRC rule data set failed");
2118                         return -1;
2119                 }
2120
2121                 ret = dpaa2_flow_rule_data_set(
2122                                 &priv->extract.tc_key_extract[group],
2123                                 &flow->fs_rule,
2124                                 NET_PROT_TCP,
2125                                 NH_FLD_TCP_PORT_SRC,
2126                                 &spec->hdr.src_port,
2127                                 &mask->hdr.src_port,
2128                                 NH_FLD_TCP_PORT_SIZE);
2129                 if (ret) {
2130                         DPAA2_PMD_ERR(
2131                                 "FS NH_FLD_TCP_PORT_SRC rule data set failed");
2132                         return -1;
2133                 }
2134         }
2135
2136         if (mask->hdr.dst_port) {
2137                 index = dpaa2_flow_extract_search(
2138                                 &priv->extract.qos_key_extract.dpkg,
2139                                 NET_PROT_TCP, NH_FLD_TCP_PORT_DST);
2140                 if (index < 0) {
2141                         ret = dpaa2_flow_extract_add(
2142                                         &priv->extract.qos_key_extract,
2143                                         NET_PROT_TCP,
2144                                         NH_FLD_TCP_PORT_DST,
2145                                         NH_FLD_TCP_PORT_SIZE);
2146                         if (ret) {
2147                                 DPAA2_PMD_ERR("QoS Extract add TCP_DST failed.");
2148
2149                                 return -1;
2150                         }
2151                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2152                 }
2153
2154                 index = dpaa2_flow_extract_search(
2155                                 &priv->extract.tc_key_extract[group].dpkg,
2156                                 NET_PROT_TCP, NH_FLD_TCP_PORT_DST);
2157                 if (index < 0) {
2158                         ret = dpaa2_flow_extract_add(
2159                                         &priv->extract.tc_key_extract[group],
2160                                         NET_PROT_TCP,
2161                                         NH_FLD_TCP_PORT_DST,
2162                                         NH_FLD_TCP_PORT_SIZE);
2163                         if (ret) {
2164                                 DPAA2_PMD_ERR("FS Extract add TCP_DST failed.");
2165
2166                                 return -1;
2167                         }
2168                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2169                 }
2170
2171                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2172                 if (ret) {
2173                         DPAA2_PMD_ERR(
2174                                 "Move ipaddr before TCP_PORT_DST set failed");
2175                         return -1;
2176                 }
2177
2178                 ret = dpaa2_flow_rule_data_set(
2179                                 &priv->extract.qos_key_extract,
2180                                 &flow->qos_rule,
2181                                 NET_PROT_TCP,
2182                                 NH_FLD_TCP_PORT_DST,
2183                                 &spec->hdr.dst_port,
2184                                 &mask->hdr.dst_port,
2185                                 NH_FLD_TCP_PORT_SIZE);
2186                 if (ret) {
2187                         DPAA2_PMD_ERR(
2188                                 "QoS NH_FLD_TCP_PORT_DST rule data set failed");
2189                         return -1;
2190                 }
2191
2192                 ret = dpaa2_flow_rule_data_set(
2193                                 &priv->extract.tc_key_extract[group],
2194                                 &flow->fs_rule,
2195                                 NET_PROT_TCP,
2196                                 NH_FLD_TCP_PORT_DST,
2197                                 &spec->hdr.dst_port,
2198                                 &mask->hdr.dst_port,
2199                                 NH_FLD_TCP_PORT_SIZE);
2200                 if (ret) {
2201                         DPAA2_PMD_ERR(
2202                                 "FS NH_FLD_TCP_PORT_DST rule data set failed");
2203                         return -1;
2204                 }
2205         }
2206
2207         (*device_configured) |= local_cfg;
2208
2209         return 0;
2210 }
2211
2212 static int
2213 dpaa2_configure_flow_sctp(struct rte_flow *flow,
2214                           struct rte_eth_dev *dev,
2215                           const struct rte_flow_attr *attr,
2216                           const struct rte_flow_item *pattern,
2217                           const struct rte_flow_action actions[] __rte_unused,
2218                           struct rte_flow_error *error __rte_unused,
2219                           int *device_configured)
2220 {
2221         int index, ret;
2222         int local_cfg = 0;
2223         uint32_t group;
2224         const struct rte_flow_item_sctp *spec, *mask;
2225
2226         const struct rte_flow_item_sctp *last __rte_unused;
2227         struct dpaa2_dev_priv *priv = dev->data->dev_private;
2228
2229         group = attr->group;
2230
2231         /* Parse pattern list to get the matching parameters */
2232         spec    = (const struct rte_flow_item_sctp *)pattern->spec;
2233         last    = (const struct rte_flow_item_sctp *)pattern->last;
2234         mask    = (const struct rte_flow_item_sctp *)
2235                         (pattern->mask ? pattern->mask :
2236                                 &dpaa2_flow_item_sctp_mask);
2237
2238         /* Get traffic class index and flow id to be configured */
2239         flow->tc_id = group;
2240         flow->tc_index = attr->priority;
2241
2242         if (!spec || !mc_l4_port_identification) {
2243                 struct proto_discrimination proto;
2244
2245                 index = dpaa2_flow_extract_search(
2246                                 &priv->extract.qos_key_extract.dpkg,
2247                                 NET_PROT_IP, NH_FLD_IP_PROTO);
2248                 if (index < 0) {
2249                         ret = dpaa2_flow_proto_discrimination_extract(
2250                                         &priv->extract.qos_key_extract,
2251                                         DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2252                         if (ret) {
2253                                 DPAA2_PMD_ERR(
2254                                         "QoS Extract IP protocol to discriminate SCTP failed.");
2255
2256                                 return -1;
2257                         }
2258                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2259                 }
2260
2261                 index = dpaa2_flow_extract_search(
2262                                 &priv->extract.tc_key_extract[group].dpkg,
2263                                 NET_PROT_IP, NH_FLD_IP_PROTO);
2264                 if (index < 0) {
2265                         ret = dpaa2_flow_proto_discrimination_extract(
2266                                         &priv->extract.tc_key_extract[group],
2267                                         DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2268                         if (ret) {
2269                                 DPAA2_PMD_ERR(
2270                                         "FS Extract IP protocol to discriminate SCTP failed.");
2271
2272                                 return -1;
2273                         }
2274                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2275                 }
2276
2277                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2278                 if (ret) {
2279                         DPAA2_PMD_ERR(
2280                                 "Move ipaddr before SCTP discrimination set failed");
2281                         return -1;
2282                 }
2283
2284                 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
2285                 proto.ip_proto = IPPROTO_SCTP;
2286                 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
2287                                                         proto, group);
2288                 if (ret) {
2289                         DPAA2_PMD_ERR("SCTP discrimination rule set failed");
2290                         return -1;
2291                 }
2292
2293                 (*device_configured) |= local_cfg;
2294
2295                 if (!spec)
2296                         return 0;
2297         }
2298
2299         if (dpaa2_flow_extract_support((const uint8_t *)mask,
2300                 RTE_FLOW_ITEM_TYPE_SCTP)) {
2301                 DPAA2_PMD_WARN("Extract field(s) of SCTP not support.");
2302
2303                 return -1;
2304         }
2305
2306         if (mask->hdr.src_port) {
2307                 index = dpaa2_flow_extract_search(
2308                                 &priv->extract.qos_key_extract.dpkg,
2309                                 NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC);
2310                 if (index < 0) {
2311                         ret = dpaa2_flow_extract_add(
2312                                         &priv->extract.qos_key_extract,
2313                                         NET_PROT_SCTP,
2314                                         NH_FLD_SCTP_PORT_SRC,
2315                                         NH_FLD_SCTP_PORT_SIZE);
2316                         if (ret) {
2317                                 DPAA2_PMD_ERR("QoS Extract add SCTP_SRC failed.");
2318
2319                                 return -1;
2320                         }
2321                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2322                 }
2323
2324                 index = dpaa2_flow_extract_search(
2325                                 &priv->extract.tc_key_extract[group].dpkg,
2326                                 NET_PROT_SCTP, NH_FLD_SCTP_PORT_SRC);
2327                 if (index < 0) {
2328                         ret = dpaa2_flow_extract_add(
2329                                         &priv->extract.tc_key_extract[group],
2330                                         NET_PROT_SCTP,
2331                                         NH_FLD_SCTP_PORT_SRC,
2332                                         NH_FLD_SCTP_PORT_SIZE);
2333                         if (ret) {
2334                                 DPAA2_PMD_ERR("FS Extract add SCTP_SRC failed.");
2335
2336                                 return -1;
2337                         }
2338                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2339                 }
2340
2341                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2342                 if (ret) {
2343                         DPAA2_PMD_ERR(
2344                                 "Move ipaddr before SCTP_PORT_SRC set failed");
2345                         return -1;
2346                 }
2347
2348                 ret = dpaa2_flow_rule_data_set(
2349                                 &priv->extract.qos_key_extract,
2350                                 &flow->qos_rule,
2351                                 NET_PROT_SCTP,
2352                                 NH_FLD_SCTP_PORT_SRC,
2353                                 &spec->hdr.src_port,
2354                                 &mask->hdr.src_port,
2355                                 NH_FLD_SCTP_PORT_SIZE);
2356                 if (ret) {
2357                         DPAA2_PMD_ERR(
2358                                 "QoS NH_FLD_SCTP_PORT_SRC rule data set failed");
2359                         return -1;
2360                 }
2361
2362                 ret = dpaa2_flow_rule_data_set(
2363                                 &priv->extract.tc_key_extract[group],
2364                                 &flow->fs_rule,
2365                                 NET_PROT_SCTP,
2366                                 NH_FLD_SCTP_PORT_SRC,
2367                                 &spec->hdr.src_port,
2368                                 &mask->hdr.src_port,
2369                                 NH_FLD_SCTP_PORT_SIZE);
2370                 if (ret) {
2371                         DPAA2_PMD_ERR(
2372                                 "FS NH_FLD_SCTP_PORT_SRC rule data set failed");
2373                         return -1;
2374                 }
2375         }
2376
2377         if (mask->hdr.dst_port) {
2378                 index = dpaa2_flow_extract_search(
2379                                 &priv->extract.qos_key_extract.dpkg,
2380                                 NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST);
2381                 if (index < 0) {
2382                         ret = dpaa2_flow_extract_add(
2383                                         &priv->extract.qos_key_extract,
2384                                         NET_PROT_SCTP,
2385                                         NH_FLD_SCTP_PORT_DST,
2386                                         NH_FLD_SCTP_PORT_SIZE);
2387                         if (ret) {
2388                                 DPAA2_PMD_ERR("QoS Extract add SCTP_DST failed.");
2389
2390                                 return -1;
2391                         }
2392                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2393                 }
2394
2395                 index = dpaa2_flow_extract_search(
2396                                 &priv->extract.tc_key_extract[group].dpkg,
2397                                 NET_PROT_SCTP, NH_FLD_SCTP_PORT_DST);
2398                 if (index < 0) {
2399                         ret = dpaa2_flow_extract_add(
2400                                         &priv->extract.tc_key_extract[group],
2401                                         NET_PROT_SCTP,
2402                                         NH_FLD_SCTP_PORT_DST,
2403                                         NH_FLD_SCTP_PORT_SIZE);
2404                         if (ret) {
2405                                 DPAA2_PMD_ERR("FS Extract add SCTP_DST failed.");
2406
2407                                 return -1;
2408                         }
2409                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2410                 }
2411
2412                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2413                 if (ret) {
2414                         DPAA2_PMD_ERR(
2415                                 "Move ipaddr before SCTP_PORT_DST set failed");
2416                         return -1;
2417                 }
2418
2419                 ret = dpaa2_flow_rule_data_set(
2420                                 &priv->extract.qos_key_extract,
2421                                 &flow->qos_rule,
2422                                 NET_PROT_SCTP,
2423                                 NH_FLD_SCTP_PORT_DST,
2424                                 &spec->hdr.dst_port,
2425                                 &mask->hdr.dst_port,
2426                                 NH_FLD_SCTP_PORT_SIZE);
2427                 if (ret) {
2428                         DPAA2_PMD_ERR(
2429                                 "QoS NH_FLD_SCTP_PORT_DST rule data set failed");
2430                         return -1;
2431                 }
2432
2433                 ret = dpaa2_flow_rule_data_set(
2434                                 &priv->extract.tc_key_extract[group],
2435                                 &flow->fs_rule,
2436                                 NET_PROT_SCTP,
2437                                 NH_FLD_SCTP_PORT_DST,
2438                                 &spec->hdr.dst_port,
2439                                 &mask->hdr.dst_port,
2440                                 NH_FLD_SCTP_PORT_SIZE);
2441                 if (ret) {
2442                         DPAA2_PMD_ERR(
2443                                 "FS NH_FLD_SCTP_PORT_DST rule data set failed");
2444                         return -1;
2445                 }
2446         }
2447
2448         (*device_configured) |= local_cfg;
2449
2450         return 0;
2451 }
2452
2453 static int
2454 dpaa2_configure_flow_gre(struct rte_flow *flow,
2455                          struct rte_eth_dev *dev,
2456                          const struct rte_flow_attr *attr,
2457                          const struct rte_flow_item *pattern,
2458                          const struct rte_flow_action actions[] __rte_unused,
2459                          struct rte_flow_error *error __rte_unused,
2460                          int *device_configured)
2461 {
2462         int index, ret;
2463         int local_cfg = 0;
2464         uint32_t group;
2465         const struct rte_flow_item_gre *spec, *mask;
2466
2467         const struct rte_flow_item_gre *last __rte_unused;
2468         struct dpaa2_dev_priv *priv = dev->data->dev_private;
2469
2470         group = attr->group;
2471
2472         /* Parse pattern list to get the matching parameters */
2473         spec    = (const struct rte_flow_item_gre *)pattern->spec;
2474         last    = (const struct rte_flow_item_gre *)pattern->last;
2475         mask    = (const struct rte_flow_item_gre *)
2476                 (pattern->mask ? pattern->mask : &dpaa2_flow_item_gre_mask);
2477
2478         /* Get traffic class index and flow id to be configured */
2479         flow->tc_id = group;
2480         flow->tc_index = attr->priority;
2481
2482         if (!spec) {
2483                 struct proto_discrimination proto;
2484
2485                 index = dpaa2_flow_extract_search(
2486                                 &priv->extract.qos_key_extract.dpkg,
2487                                 NET_PROT_IP, NH_FLD_IP_PROTO);
2488                 if (index < 0) {
2489                         ret = dpaa2_flow_proto_discrimination_extract(
2490                                         &priv->extract.qos_key_extract,
2491                                         DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2492                         if (ret) {
2493                                 DPAA2_PMD_ERR(
2494                                         "QoS Extract IP protocol to discriminate GRE failed.");
2495
2496                                 return -1;
2497                         }
2498                         local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2499                 }
2500
2501                 index = dpaa2_flow_extract_search(
2502                                 &priv->extract.tc_key_extract[group].dpkg,
2503                                 NET_PROT_IP, NH_FLD_IP_PROTO);
2504                 if (index < 0) {
2505                         ret = dpaa2_flow_proto_discrimination_extract(
2506                                         &priv->extract.tc_key_extract[group],
2507                                         DPAA2_FLOW_ITEM_TYPE_GENERIC_IP);
2508                         if (ret) {
2509                                 DPAA2_PMD_ERR(
2510                                         "FS Extract IP protocol to discriminate GRE failed.");
2511
2512                                 return -1;
2513                         }
2514                         local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2515                 }
2516
2517                 ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2518                 if (ret) {
2519                         DPAA2_PMD_ERR(
2520                                 "Move IP addr before GRE discrimination set failed");
2521                         return -1;
2522                 }
2523
2524                 proto.type = DPAA2_FLOW_ITEM_TYPE_GENERIC_IP;
2525                 proto.ip_proto = IPPROTO_GRE;
2526                 ret = dpaa2_flow_proto_discrimination_rule(priv, flow,
2527                                                         proto, group);
2528                 if (ret) {
2529                         DPAA2_PMD_ERR("GRE discrimination rule set failed");
2530                         return -1;
2531                 }
2532
2533                 (*device_configured) |= local_cfg;
2534
2535                 return 0;
2536         }
2537
2538         if (dpaa2_flow_extract_support((const uint8_t *)mask,
2539                 RTE_FLOW_ITEM_TYPE_GRE)) {
2540                 DPAA2_PMD_WARN("Extract field(s) of GRE not support.");
2541
2542                 return -1;
2543         }
2544
2545         if (!mask->protocol)
2546                 return 0;
2547
2548         index = dpaa2_flow_extract_search(
2549                         &priv->extract.qos_key_extract.dpkg,
2550                         NET_PROT_GRE, NH_FLD_GRE_TYPE);
2551         if (index < 0) {
2552                 ret = dpaa2_flow_extract_add(
2553                                 &priv->extract.qos_key_extract,
2554                                 NET_PROT_GRE,
2555                                 NH_FLD_GRE_TYPE,
2556                                 sizeof(rte_be16_t));
2557                 if (ret) {
2558                         DPAA2_PMD_ERR("QoS Extract add GRE_TYPE failed.");
2559
2560                         return -1;
2561                 }
2562                 local_cfg |= DPAA2_QOS_TABLE_RECONFIGURE;
2563         }
2564
2565         index = dpaa2_flow_extract_search(
2566                         &priv->extract.tc_key_extract[group].dpkg,
2567                         NET_PROT_GRE, NH_FLD_GRE_TYPE);
2568         if (index < 0) {
2569                 ret = dpaa2_flow_extract_add(
2570                                 &priv->extract.tc_key_extract[group],
2571                                 NET_PROT_GRE,
2572                                 NH_FLD_GRE_TYPE,
2573                                 sizeof(rte_be16_t));
2574                 if (ret) {
2575                         DPAA2_PMD_ERR("FS Extract add GRE_TYPE failed.");
2576
2577                         return -1;
2578                 }
2579                 local_cfg |= DPAA2_FS_TABLE_RECONFIGURE;
2580         }
2581
2582         ret = dpaa2_flow_rule_move_ipaddr_tail(flow, priv, group);
2583         if (ret) {
2584                 DPAA2_PMD_ERR(
2585                         "Move ipaddr before GRE_TYPE set failed");
2586                 return -1;
2587         }
2588
2589         ret = dpaa2_flow_rule_data_set(
2590                                 &priv->extract.qos_key_extract,
2591                                 &flow->qos_rule,
2592                                 NET_PROT_GRE,
2593                                 NH_FLD_GRE_TYPE,
2594                                 &spec->protocol,
2595                                 &mask->protocol,
2596                                 sizeof(rte_be16_t));
2597         if (ret) {
2598                 DPAA2_PMD_ERR(
2599                         "QoS NH_FLD_GRE_TYPE rule data set failed");
2600                 return -1;
2601         }
2602
2603         ret = dpaa2_flow_rule_data_set(
2604                         &priv->extract.tc_key_extract[group],
2605                         &flow->fs_rule,
2606                         NET_PROT_GRE,
2607                         NH_FLD_GRE_TYPE,
2608                         &spec->protocol,
2609                         &mask->protocol,
2610                         sizeof(rte_be16_t));
2611         if (ret) {
2612                 DPAA2_PMD_ERR(
2613                         "FS NH_FLD_GRE_TYPE rule data set failed");
2614                 return -1;
2615         }
2616
2617         (*device_configured) |= local_cfg;
2618
2619         return 0;
2620 }
2621
2622 /* The existing QoS/FS entry with IP address(es)
2623  * needs update after
2624  * new extract(s) are inserted before IP
2625  * address(es) extract(s).
2626  */
2627 static int
2628 dpaa2_flow_entry_update(
2629         struct dpaa2_dev_priv *priv, uint8_t tc_id)
2630 {
2631         struct rte_flow *curr = LIST_FIRST(&priv->flows);
2632         struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
2633         int ret;
2634         int qos_ipsrc_offset = -1, qos_ipdst_offset = -1;
2635         int fs_ipsrc_offset = -1, fs_ipdst_offset = -1;
2636         struct dpaa2_key_extract *qos_key_extract =
2637                 &priv->extract.qos_key_extract;
2638         struct dpaa2_key_extract *tc_key_extract =
2639                 &priv->extract.tc_key_extract[tc_id];
2640         char ipsrc_key[NH_FLD_IPV6_ADDR_SIZE];
2641         char ipdst_key[NH_FLD_IPV6_ADDR_SIZE];
2642         char ipsrc_mask[NH_FLD_IPV6_ADDR_SIZE];
2643         char ipdst_mask[NH_FLD_IPV6_ADDR_SIZE];
2644         int extend = -1, extend1, size;
2645         uint16_t qos_index;
2646
2647         while (curr) {
2648                 if (curr->ipaddr_rule.ipaddr_type ==
2649                         FLOW_NONE_IPADDR) {
2650                         curr = LIST_NEXT(curr, next);
2651                         continue;
2652                 }
2653
2654                 if (curr->ipaddr_rule.ipaddr_type ==
2655                         FLOW_IPV4_ADDR) {
2656                         qos_ipsrc_offset =
2657                                 qos_key_extract->key_info.ipv4_src_offset;
2658                         qos_ipdst_offset =
2659                                 qos_key_extract->key_info.ipv4_dst_offset;
2660                         fs_ipsrc_offset =
2661                                 tc_key_extract->key_info.ipv4_src_offset;
2662                         fs_ipdst_offset =
2663                                 tc_key_extract->key_info.ipv4_dst_offset;
2664                         size = NH_FLD_IPV4_ADDR_SIZE;
2665                 } else {
2666                         qos_ipsrc_offset =
2667                                 qos_key_extract->key_info.ipv6_src_offset;
2668                         qos_ipdst_offset =
2669                                 qos_key_extract->key_info.ipv6_dst_offset;
2670                         fs_ipsrc_offset =
2671                                 tc_key_extract->key_info.ipv6_src_offset;
2672                         fs_ipdst_offset =
2673                                 tc_key_extract->key_info.ipv6_dst_offset;
2674                         size = NH_FLD_IPV6_ADDR_SIZE;
2675                 }
2676
2677                 qos_index = curr->tc_id * priv->fs_entries +
2678                         curr->tc_index;
2679
2680                 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
2681                                 priv->token, &curr->qos_rule);
2682                 if (ret) {
2683                         DPAA2_PMD_ERR("Qos entry remove failed.");
2684                         return -1;
2685                 }
2686
2687                 extend = -1;
2688
2689                 if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {
2690                         RTE_ASSERT(qos_ipsrc_offset >=
2691                                 curr->ipaddr_rule.qos_ipsrc_offset);
2692                         extend1 = qos_ipsrc_offset -
2693                                 curr->ipaddr_rule.qos_ipsrc_offset;
2694                         if (extend >= 0)
2695                                 RTE_ASSERT(extend == extend1);
2696                         else
2697                                 extend = extend1;
2698
2699                         memcpy(ipsrc_key,
2700                                 (char *)(size_t)curr->qos_rule.key_iova +
2701                                 curr->ipaddr_rule.qos_ipsrc_offset,
2702                                 size);
2703                         memset((char *)(size_t)curr->qos_rule.key_iova +
2704                                 curr->ipaddr_rule.qos_ipsrc_offset,
2705                                 0, size);
2706
2707                         memcpy(ipsrc_mask,
2708                                 (char *)(size_t)curr->qos_rule.mask_iova +
2709                                 curr->ipaddr_rule.qos_ipsrc_offset,
2710                                 size);
2711                         memset((char *)(size_t)curr->qos_rule.mask_iova +
2712                                 curr->ipaddr_rule.qos_ipsrc_offset,
2713                                 0, size);
2714
2715                         curr->ipaddr_rule.qos_ipsrc_offset = qos_ipsrc_offset;
2716                 }
2717
2718                 if (curr->ipaddr_rule.qos_ipdst_offset >= 0) {
2719                         RTE_ASSERT(qos_ipdst_offset >=
2720                                 curr->ipaddr_rule.qos_ipdst_offset);
2721                         extend1 = qos_ipdst_offset -
2722                                 curr->ipaddr_rule.qos_ipdst_offset;
2723                         if (extend >= 0)
2724                                 RTE_ASSERT(extend == extend1);
2725                         else
2726                                 extend = extend1;
2727
2728                         memcpy(ipdst_key,
2729                                 (char *)(size_t)curr->qos_rule.key_iova +
2730                                 curr->ipaddr_rule.qos_ipdst_offset,
2731                                 size);
2732                         memset((char *)(size_t)curr->qos_rule.key_iova +
2733                                 curr->ipaddr_rule.qos_ipdst_offset,
2734                                 0, size);
2735
2736                         memcpy(ipdst_mask,
2737                                 (char *)(size_t)curr->qos_rule.mask_iova +
2738                                 curr->ipaddr_rule.qos_ipdst_offset,
2739                                 size);
2740                         memset((char *)(size_t)curr->qos_rule.mask_iova +
2741                                 curr->ipaddr_rule.qos_ipdst_offset,
2742                                 0, size);
2743
2744                         curr->ipaddr_rule.qos_ipdst_offset = qos_ipdst_offset;
2745                 }
2746
2747                 if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {
2748                         memcpy((char *)(size_t)curr->qos_rule.key_iova +
2749                                 curr->ipaddr_rule.qos_ipsrc_offset,
2750                                 ipsrc_key,
2751                                 size);
2752                         memcpy((char *)(size_t)curr->qos_rule.mask_iova +
2753                                 curr->ipaddr_rule.qos_ipsrc_offset,
2754                                 ipsrc_mask,
2755                                 size);
2756                 }
2757                 if (curr->ipaddr_rule.qos_ipdst_offset >= 0) {
2758                         memcpy((char *)(size_t)curr->qos_rule.key_iova +
2759                                 curr->ipaddr_rule.qos_ipdst_offset,
2760                                 ipdst_key,
2761                                 size);
2762                         memcpy((char *)(size_t)curr->qos_rule.mask_iova +
2763                                 curr->ipaddr_rule.qos_ipdst_offset,
2764                                 ipdst_mask,
2765                                 size);
2766                 }
2767
2768                 if (extend >= 0)
2769                         curr->qos_rule.key_size += extend;
2770
2771                 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
2772                                 priv->token, &curr->qos_rule,
2773                                 curr->tc_id, qos_index,
2774                                 0, 0);
2775                 if (ret) {
2776                         DPAA2_PMD_ERR("Qos entry update failed.");
2777                         return -1;
2778                 }
2779
2780                 if (curr->action != RTE_FLOW_ACTION_TYPE_QUEUE) {
2781                         curr = LIST_NEXT(curr, next);
2782                         continue;
2783                 }
2784
2785                 extend = -1;
2786
2787                 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW,
2788                                 priv->token, curr->tc_id, &curr->fs_rule);
2789                 if (ret) {
2790                         DPAA2_PMD_ERR("FS entry remove failed.");
2791                         return -1;
2792                 }
2793
2794                 if (curr->ipaddr_rule.fs_ipsrc_offset >= 0 &&
2795                         tc_id == curr->tc_id) {
2796                         RTE_ASSERT(fs_ipsrc_offset >=
2797                                 curr->ipaddr_rule.fs_ipsrc_offset);
2798                         extend1 = fs_ipsrc_offset -
2799                                 curr->ipaddr_rule.fs_ipsrc_offset;
2800                         if (extend >= 0)
2801                                 RTE_ASSERT(extend == extend1);
2802                         else
2803                                 extend = extend1;
2804
2805                         memcpy(ipsrc_key,
2806                                 (char *)(size_t)curr->fs_rule.key_iova +
2807                                 curr->ipaddr_rule.fs_ipsrc_offset,
2808                                 size);
2809                         memset((char *)(size_t)curr->fs_rule.key_iova +
2810                                 curr->ipaddr_rule.fs_ipsrc_offset,
2811                                 0, size);
2812
2813                         memcpy(ipsrc_mask,
2814                                 (char *)(size_t)curr->fs_rule.mask_iova +
2815                                 curr->ipaddr_rule.fs_ipsrc_offset,
2816                                 size);
2817                         memset((char *)(size_t)curr->fs_rule.mask_iova +
2818                                 curr->ipaddr_rule.fs_ipsrc_offset,
2819                                 0, size);
2820
2821                         curr->ipaddr_rule.fs_ipsrc_offset = fs_ipsrc_offset;
2822                 }
2823
2824                 if (curr->ipaddr_rule.fs_ipdst_offset >= 0 &&
2825                         tc_id == curr->tc_id) {
2826                         RTE_ASSERT(fs_ipdst_offset >=
2827                                 curr->ipaddr_rule.fs_ipdst_offset);
2828                         extend1 = fs_ipdst_offset -
2829                                 curr->ipaddr_rule.fs_ipdst_offset;
2830                         if (extend >= 0)
2831                                 RTE_ASSERT(extend == extend1);
2832                         else
2833                                 extend = extend1;
2834
2835                         memcpy(ipdst_key,
2836                                 (char *)(size_t)curr->fs_rule.key_iova +
2837                                 curr->ipaddr_rule.fs_ipdst_offset,
2838                                 size);
2839                         memset((char *)(size_t)curr->fs_rule.key_iova +
2840                                 curr->ipaddr_rule.fs_ipdst_offset,
2841                                 0, size);
2842
2843                         memcpy(ipdst_mask,
2844                                 (char *)(size_t)curr->fs_rule.mask_iova +
2845                                 curr->ipaddr_rule.fs_ipdst_offset,
2846                                 size);
2847                         memset((char *)(size_t)curr->fs_rule.mask_iova +
2848                                 curr->ipaddr_rule.fs_ipdst_offset,
2849                                 0, size);
2850
2851                         curr->ipaddr_rule.fs_ipdst_offset = fs_ipdst_offset;
2852                 }
2853
2854                 if (curr->ipaddr_rule.fs_ipsrc_offset >= 0) {
2855                         memcpy((char *)(size_t)curr->fs_rule.key_iova +
2856                                 curr->ipaddr_rule.fs_ipsrc_offset,
2857                                 ipsrc_key,
2858                                 size);
2859                         memcpy((char *)(size_t)curr->fs_rule.mask_iova +
2860                                 curr->ipaddr_rule.fs_ipsrc_offset,
2861                                 ipsrc_mask,
2862                                 size);
2863                 }
2864                 if (curr->ipaddr_rule.fs_ipdst_offset >= 0) {
2865                         memcpy((char *)(size_t)curr->fs_rule.key_iova +
2866                                 curr->ipaddr_rule.fs_ipdst_offset,
2867                                 ipdst_key,
2868                                 size);
2869                         memcpy((char *)(size_t)curr->fs_rule.mask_iova +
2870                                 curr->ipaddr_rule.fs_ipdst_offset,
2871                                 ipdst_mask,
2872                                 size);
2873                 }
2874
2875                 if (extend >= 0)
2876                         curr->fs_rule.key_size += extend;
2877
2878                 ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,
2879                                 priv->token, curr->tc_id, curr->tc_index,
2880                                 &curr->fs_rule, &curr->action_cfg);
2881                 if (ret) {
2882                         DPAA2_PMD_ERR("FS entry update failed.");
2883                         return -1;
2884                 }
2885
2886                 curr = LIST_NEXT(curr, next);
2887         }
2888
2889         return 0;
2890 }
2891
2892 static inline int
2893 dpaa2_flow_verify_attr(
2894         struct dpaa2_dev_priv *priv,
2895         const struct rte_flow_attr *attr)
2896 {
2897         struct rte_flow *curr = LIST_FIRST(&priv->flows);
2898
2899         while (curr) {
2900                 if (curr->tc_id == attr->group &&
2901                         curr->tc_index == attr->priority) {
2902                         DPAA2_PMD_ERR(
2903                                 "Flow with group %d and priority %d already exists.",
2904                                 attr->group, attr->priority);
2905
2906                         return -1;
2907                 }
2908                 curr = LIST_NEXT(curr, next);
2909         }
2910
2911         return 0;
2912 }
2913
2914 static int
2915 dpaa2_generic_flow_set(struct rte_flow *flow,
2916                        struct rte_eth_dev *dev,
2917                        const struct rte_flow_attr *attr,
2918                        const struct rte_flow_item pattern[],
2919                        const struct rte_flow_action actions[],
2920                        struct rte_flow_error *error)
2921 {
2922         const struct rte_flow_action_queue *dest_queue;
2923         const struct rte_flow_action_rss *rss_conf;
2924         int is_keycfg_configured = 0, end_of_list = 0;
2925         int ret = 0, i = 0, j = 0;
2926         struct dpni_rx_tc_dist_cfg tc_cfg;
2927         struct dpni_qos_tbl_cfg qos_cfg;
2928         struct dpni_fs_action_cfg action;
2929         struct dpaa2_dev_priv *priv = dev->data->dev_private;
2930         struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
2931         size_t param;
2932         struct rte_flow *curr = LIST_FIRST(&priv->flows);
2933         uint16_t qos_index;
2934
2935         ret = dpaa2_flow_verify_attr(priv, attr);
2936         if (ret)
2937                 return ret;
2938
2939         /* Parse pattern list to get the matching parameters */
2940         while (!end_of_list) {
2941                 switch (pattern[i].type) {
2942                 case RTE_FLOW_ITEM_TYPE_ETH:
2943                         ret = dpaa2_configure_flow_eth(flow,
2944                                         dev, attr, &pattern[i], actions, error,
2945                                         &is_keycfg_configured);
2946                         if (ret) {
2947                                 DPAA2_PMD_ERR("ETH flow configuration failed!");
2948                                 return ret;
2949                         }
2950                         break;
2951                 case RTE_FLOW_ITEM_TYPE_VLAN:
2952                         ret = dpaa2_configure_flow_vlan(flow,
2953                                         dev, attr, &pattern[i], actions, error,
2954                                         &is_keycfg_configured);
2955                         if (ret) {
2956                                 DPAA2_PMD_ERR("vLan flow configuration failed!");
2957                                 return ret;
2958                         }
2959                         break;
2960                 case RTE_FLOW_ITEM_TYPE_IPV4:
2961                 case RTE_FLOW_ITEM_TYPE_IPV6:
2962                         ret = dpaa2_configure_flow_generic_ip(flow,
2963                                         dev, attr, &pattern[i], actions, error,
2964                                         &is_keycfg_configured);
2965                         if (ret) {
2966                                 DPAA2_PMD_ERR("IP flow configuration failed!");
2967                                 return ret;
2968                         }
2969                         break;
2970                 case RTE_FLOW_ITEM_TYPE_ICMP:
2971                         ret = dpaa2_configure_flow_icmp(flow,
2972                                         dev, attr, &pattern[i], actions, error,
2973                                         &is_keycfg_configured);
2974                         if (ret) {
2975                                 DPAA2_PMD_ERR("ICMP flow configuration failed!");
2976                                 return ret;
2977                         }
2978                         break;
2979                 case RTE_FLOW_ITEM_TYPE_UDP:
2980                         ret = dpaa2_configure_flow_udp(flow,
2981                                         dev, attr, &pattern[i], actions, error,
2982                                         &is_keycfg_configured);
2983                         if (ret) {
2984                                 DPAA2_PMD_ERR("UDP flow configuration failed!");
2985                                 return ret;
2986                         }
2987                         break;
2988                 case RTE_FLOW_ITEM_TYPE_TCP:
2989                         ret = dpaa2_configure_flow_tcp(flow,
2990                                         dev, attr, &pattern[i], actions, error,
2991                                         &is_keycfg_configured);
2992                         if (ret) {
2993                                 DPAA2_PMD_ERR("TCP flow configuration failed!");
2994                                 return ret;
2995                         }
2996                         break;
2997                 case RTE_FLOW_ITEM_TYPE_SCTP:
2998                         ret = dpaa2_configure_flow_sctp(flow,
2999                                         dev, attr, &pattern[i], actions, error,
3000                                         &is_keycfg_configured);
3001                         if (ret) {
3002                                 DPAA2_PMD_ERR("SCTP flow configuration failed!");
3003                                 return ret;
3004                         }
3005                         break;
3006                 case RTE_FLOW_ITEM_TYPE_GRE:
3007                         ret = dpaa2_configure_flow_gre(flow,
3008                                         dev, attr, &pattern[i], actions, error,
3009                                         &is_keycfg_configured);
3010                         if (ret) {
3011                                 DPAA2_PMD_ERR("GRE flow configuration failed!");
3012                                 return ret;
3013                         }
3014                         break;
3015                 case RTE_FLOW_ITEM_TYPE_END:
3016                         end_of_list = 1;
3017                         break; /*End of List*/
3018                 default:
3019                         DPAA2_PMD_ERR("Invalid action type");
3020                         ret = -ENOTSUP;
3021                         break;
3022                 }
3023                 i++;
3024         }
3025
3026         /* Let's parse action on matching traffic */
3027         end_of_list = 0;
3028         while (!end_of_list) {
3029                 switch (actions[j].type) {
3030                 case RTE_FLOW_ACTION_TYPE_QUEUE:
3031                         dest_queue = (const struct rte_flow_action_queue *)(actions[j].conf);
3032                         flow->flow_id = dest_queue->index;
3033                         flow->action = RTE_FLOW_ACTION_TYPE_QUEUE;
3034                         memset(&action, 0, sizeof(struct dpni_fs_action_cfg));
3035                         action.flow_id = flow->flow_id;
3036                         if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
3037                                 if (dpkg_prepare_key_cfg(&priv->extract.qos_key_extract.dpkg,
3038                                         (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
3039                                         DPAA2_PMD_ERR(
3040                                         "Unable to prepare extract parameters");
3041                                         return -1;
3042                                 }
3043
3044                                 memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg));
3045                                 qos_cfg.discard_on_miss = true;
3046                                 qos_cfg.keep_entries = true;
3047                                 qos_cfg.key_cfg_iova = (size_t)priv->extract.qos_extract_param;
3048                                 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
3049                                                 priv->token, &qos_cfg);
3050                                 if (ret < 0) {
3051                                         DPAA2_PMD_ERR(
3052                                         "Distribution cannot be configured.(%d)"
3053                                         , ret);
3054                                         return -1;
3055                                 }
3056                         }
3057                         if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) {
3058                                 if (dpkg_prepare_key_cfg(
3059                                 &priv->extract.tc_key_extract[flow->tc_id].dpkg,
3060                                 (uint8_t *)(size_t)priv->extract
3061                                 .tc_extract_param[flow->tc_id]) < 0) {
3062                                         DPAA2_PMD_ERR(
3063                                         "Unable to prepare extract parameters");
3064                                         return -1;
3065                                 }
3066
3067                                 memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
3068                                 tc_cfg.dist_size = priv->nb_rx_queues / priv->num_rx_tc;
3069                                 tc_cfg.dist_mode = DPNI_DIST_MODE_FS;
3070                                 tc_cfg.key_cfg_iova =
3071                                         (uint64_t)priv->extract.tc_extract_param[flow->tc_id];
3072                                 tc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP;
3073                                 tc_cfg.fs_cfg.keep_entries = true;
3074                                 ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW,
3075                                                          priv->token,
3076                                                          flow->tc_id, &tc_cfg);
3077                                 if (ret < 0) {
3078                                         DPAA2_PMD_ERR(
3079                                         "Distribution cannot be configured.(%d)"
3080                                         , ret);
3081                                         return -1;
3082                                 }
3083                         }
3084                         /* Configure QoS table first */
3085
3086                         action.flow_id = action.flow_id % priv->num_rx_tc;
3087
3088                         qos_index = flow->tc_id * priv->fs_entries +
3089                                 flow->tc_index;
3090
3091                         if (qos_index >= priv->qos_entries) {
3092                                 DPAA2_PMD_ERR("QoS table with %d entries full",
3093                                         priv->qos_entries);
3094                                 return -1;
3095                         }
3096                         flow->qos_rule.key_size = priv->extract
3097                                 .qos_key_extract.key_info.key_total_size;
3098                         if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR) {
3099                                 if (flow->ipaddr_rule.qos_ipdst_offset >=
3100                                         flow->ipaddr_rule.qos_ipsrc_offset) {
3101                                         flow->qos_rule.key_size =
3102                                                 flow->ipaddr_rule.qos_ipdst_offset +
3103                                                 NH_FLD_IPV4_ADDR_SIZE;
3104                                 } else {
3105                                         flow->qos_rule.key_size =
3106                                                 flow->ipaddr_rule.qos_ipsrc_offset +
3107                                                 NH_FLD_IPV4_ADDR_SIZE;
3108                                 }
3109                         } else if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV6_ADDR) {
3110                                 if (flow->ipaddr_rule.qos_ipdst_offset >=
3111                                         flow->ipaddr_rule.qos_ipsrc_offset) {
3112                                         flow->qos_rule.key_size =
3113                                                 flow->ipaddr_rule.qos_ipdst_offset +
3114                                                 NH_FLD_IPV6_ADDR_SIZE;
3115                                 } else {
3116                                         flow->qos_rule.key_size =
3117                                                 flow->ipaddr_rule.qos_ipsrc_offset +
3118                                                 NH_FLD_IPV6_ADDR_SIZE;
3119                                 }
3120                         }
3121                         ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
3122                                                 priv->token, &flow->qos_rule,
3123                                                 flow->tc_id, qos_index,
3124                                                 0, 0);
3125                         if (ret < 0) {
3126                                 DPAA2_PMD_ERR(
3127                                 "Error in addnig entry to QoS table(%d)", ret);
3128                                 return ret;
3129                         }
3130
3131                         /* Then Configure FS table */
3132                         if (flow->tc_index >= priv->fs_entries) {
3133                                 DPAA2_PMD_ERR("FS table with %d entries full",
3134                                         priv->fs_entries);
3135                                 return -1;
3136                         }
3137                         flow->fs_rule.key_size = priv->extract
3138                                         .tc_key_extract[attr->group].key_info.key_total_size;
3139                         if (flow->ipaddr_rule.ipaddr_type ==
3140                                 FLOW_IPV4_ADDR) {
3141                                 if (flow->ipaddr_rule.fs_ipdst_offset >=
3142                                         flow->ipaddr_rule.fs_ipsrc_offset) {
3143                                         flow->fs_rule.key_size =
3144                                                 flow->ipaddr_rule.fs_ipdst_offset +
3145                                                 NH_FLD_IPV4_ADDR_SIZE;
3146                                 } else {
3147                                         flow->fs_rule.key_size =
3148                                                 flow->ipaddr_rule.fs_ipsrc_offset +
3149                                                 NH_FLD_IPV4_ADDR_SIZE;
3150                                 }
3151                         } else if (flow->ipaddr_rule.ipaddr_type ==
3152                                 FLOW_IPV6_ADDR) {
3153                                 if (flow->ipaddr_rule.fs_ipdst_offset >=
3154                                         flow->ipaddr_rule.fs_ipsrc_offset) {
3155                                         flow->fs_rule.key_size =
3156                                                 flow->ipaddr_rule.fs_ipdst_offset +
3157                                                 NH_FLD_IPV6_ADDR_SIZE;
3158                                 } else {
3159                                         flow->fs_rule.key_size =
3160                                                 flow->ipaddr_rule.fs_ipsrc_offset +
3161                                                 NH_FLD_IPV6_ADDR_SIZE;
3162                                 }
3163                         }
3164                         ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token,
3165                                                 flow->tc_id, flow->tc_index,
3166                                                 &flow->fs_rule, &action);
3167                         if (ret < 0) {
3168                                 DPAA2_PMD_ERR(
3169                                 "Error in adding entry to FS table(%d)", ret);
3170                                 return ret;
3171                         }
3172                         memcpy(&flow->action_cfg, &action,
3173                                 sizeof(struct dpni_fs_action_cfg));
3174                         break;
3175                 case RTE_FLOW_ACTION_TYPE_RSS:
3176                         rss_conf = (const struct rte_flow_action_rss *)(actions[j].conf);
3177                         for (i = 0; i < (int)rss_conf->queue_num; i++) {
3178                                 if (rss_conf->queue[i] <
3179                                         (attr->group * priv->dist_queues) ||
3180                                         rss_conf->queue[i] >=
3181                                         ((attr->group + 1) * priv->dist_queues)) {
3182                                         DPAA2_PMD_ERR(
3183                                         "Queue/Group combination are not supported\n");
3184                                         return -ENOTSUP;
3185                                 }
3186                         }
3187
3188                         flow->action = RTE_FLOW_ACTION_TYPE_RSS;
3189                         ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types,
3190                                         &priv->extract.tc_key_extract[flow->tc_id].dpkg);
3191                         if (ret < 0) {
3192                                 DPAA2_PMD_ERR(
3193                                 "unable to set flow distribution.please check queue config\n");
3194                                 return ret;
3195                         }
3196
3197                         /* Allocate DMA'ble memory to write the rules */
3198                         param = (size_t)rte_malloc(NULL, 256, 64);
3199                         if (!param) {
3200                                 DPAA2_PMD_ERR("Memory allocation failure\n");
3201                                 return -1;
3202                         }
3203
3204                         if (dpkg_prepare_key_cfg(
3205                                 &priv->extract.tc_key_extract[flow->tc_id].dpkg,
3206                                 (uint8_t *)param) < 0) {
3207                                 DPAA2_PMD_ERR(
3208                                 "Unable to prepare extract parameters");
3209                                 rte_free((void *)param);
3210                                 return -1;
3211                         }
3212
3213                         memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
3214                         tc_cfg.dist_size = rss_conf->queue_num;
3215                         tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
3216                         tc_cfg.key_cfg_iova = (size_t)param;
3217                         tc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP;
3218
3219                         ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW,
3220                                                  priv->token, flow->tc_id,
3221                                                  &tc_cfg);
3222                         if (ret < 0) {
3223                                 DPAA2_PMD_ERR(
3224                                 "Distribution cannot be configured: %d\n", ret);
3225                                 rte_free((void *)param);
3226                                 return -1;
3227                         }
3228
3229                         rte_free((void *)param);
3230                         if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
3231                                 if (dpkg_prepare_key_cfg(
3232                                         &priv->extract.qos_key_extract.dpkg,
3233                                         (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
3234                                         DPAA2_PMD_ERR(
3235                                         "Unable to prepare extract parameters");
3236                                         return -1;
3237                                 }
3238                                 memset(&qos_cfg, 0,
3239                                         sizeof(struct dpni_qos_tbl_cfg));
3240                                 qos_cfg.discard_on_miss = true;
3241                                 qos_cfg.keep_entries = true;
3242                                 qos_cfg.key_cfg_iova =
3243                                         (size_t)priv->extract.qos_extract_param;
3244                                 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
3245                                                          priv->token, &qos_cfg);
3246                                 if (ret < 0) {
3247                                         DPAA2_PMD_ERR(
3248                                         "Distribution can't be configured %d\n",
3249                                         ret);
3250                                         return -1;
3251                                 }
3252                         }
3253
3254                         /* Add Rule into QoS table */
3255                         qos_index = flow->tc_id * priv->fs_entries +
3256                                 flow->tc_index;
3257                         if (qos_index >= priv->qos_entries) {
3258                                 DPAA2_PMD_ERR("QoS table with %d entries full",
3259                                         priv->qos_entries);
3260                                 return -1;
3261                         }
3262                         flow->qos_rule.key_size =
3263                           priv->extract.qos_key_extract.key_info.key_total_size;
3264                         ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, priv->token,
3265                                                 &flow->qos_rule, flow->tc_id,
3266                                                 qos_index, 0, 0);
3267                         if (ret < 0) {
3268                                 DPAA2_PMD_ERR(
3269                                 "Error in entry addition in QoS table(%d)",
3270                                 ret);
3271                                 return ret;
3272                         }
3273                         break;
3274                 case RTE_FLOW_ACTION_TYPE_END:
3275                         end_of_list = 1;
3276                         break;
3277                 default:
3278                         DPAA2_PMD_ERR("Invalid action type");
3279                         ret = -ENOTSUP;
3280                         break;
3281                 }
3282                 j++;
3283         }
3284
3285         if (!ret) {
3286                 ret = dpaa2_flow_entry_update(priv, flow->tc_id);
3287                 if (ret) {
3288                         DPAA2_PMD_ERR("Flow entry update failed.");
3289
3290                         return -1;
3291                 }
3292                 /* New rules are inserted. */
3293                 if (!curr) {
3294                         LIST_INSERT_HEAD(&priv->flows, flow, next);
3295                 } else {
3296                         while (LIST_NEXT(curr, next))
3297                                 curr = LIST_NEXT(curr, next);
3298                         LIST_INSERT_AFTER(curr, flow, next);
3299                 }
3300         }
3301         return ret;
3302 }
3303
3304 static inline int
3305 dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr,
3306                       const struct rte_flow_attr *attr)
3307 {
3308         int ret = 0;
3309
3310         if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) {
3311                 DPAA2_PMD_ERR("Priority group is out of range\n");
3312                 ret = -ENOTSUP;
3313         }
3314         if (unlikely(attr->priority >= dpni_attr->fs_entries)) {
3315                 DPAA2_PMD_ERR("Priority within the group is out of range\n");
3316                 ret = -ENOTSUP;
3317         }
3318         if (unlikely(attr->egress)) {
3319                 DPAA2_PMD_ERR(
3320                         "Flow configuration is not supported on egress side\n");
3321                 ret = -ENOTSUP;
3322         }
3323         if (unlikely(!attr->ingress)) {
3324                 DPAA2_PMD_ERR("Ingress flag must be configured\n");
3325                 ret = -EINVAL;
3326         }
3327         return ret;
3328 }
3329
3330 static inline int
3331 dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[])
3332 {
3333         unsigned int i, j, is_found = 0;
3334         int ret = 0;
3335
3336         for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {
3337                 for (i = 0; i < RTE_DIM(dpaa2_supported_pattern_type); i++) {
3338                         if (dpaa2_supported_pattern_type[i]
3339                                         == pattern[j].type) {
3340                                 is_found = 1;
3341                                 break;
3342                         }
3343                 }
3344                 if (!is_found) {
3345                         ret = -ENOTSUP;
3346                         break;
3347                 }
3348         }
3349         /* Lets verify other combinations of given pattern rules */
3350         for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {
3351                 if (!pattern[j].spec) {
3352                         ret = -EINVAL;
3353                         break;
3354                 }
3355         }
3356
3357         return ret;
3358 }
3359
3360 static inline int
3361 dpaa2_dev_verify_actions(const struct rte_flow_action actions[])
3362 {
3363         unsigned int i, j, is_found = 0;
3364         int ret = 0;
3365
3366         for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
3367                 for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) {
3368                         if (dpaa2_supported_action_type[i] == actions[j].type) {
3369                                 is_found = 1;
3370                                 break;
3371                         }
3372                 }
3373                 if (!is_found) {
3374                         ret = -ENOTSUP;
3375                         break;
3376                 }
3377         }
3378         for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
3379                 if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP &&
3380                                 !actions[j].conf)
3381                         ret = -EINVAL;
3382         }
3383         return ret;
3384 }
3385
3386 static
3387 int dpaa2_flow_validate(struct rte_eth_dev *dev,
3388                         const struct rte_flow_attr *flow_attr,
3389                         const struct rte_flow_item pattern[],
3390                         const struct rte_flow_action actions[],
3391                         struct rte_flow_error *error)
3392 {
3393         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3394         struct dpni_attr dpni_attr;
3395         struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
3396         uint16_t token = priv->token;
3397         int ret = 0;
3398
3399         memset(&dpni_attr, 0, sizeof(struct dpni_attr));
3400         ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr);
3401         if (ret < 0) {
3402                 DPAA2_PMD_ERR(
3403                         "Failure to get dpni@%p attribute, err code  %d\n",
3404                         dpni, ret);
3405                 rte_flow_error_set(error, EPERM,
3406                            RTE_FLOW_ERROR_TYPE_ATTR,
3407                            flow_attr, "invalid");
3408                 return ret;
3409         }
3410
3411         /* Verify input attributes */
3412         ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr);
3413         if (ret < 0) {
3414                 DPAA2_PMD_ERR(
3415                         "Invalid attributes are given\n");
3416                 rte_flow_error_set(error, EPERM,
3417                            RTE_FLOW_ERROR_TYPE_ATTR,
3418                            flow_attr, "invalid");
3419                 goto not_valid_params;
3420         }
3421         /* Verify input pattern list */
3422         ret = dpaa2_dev_verify_patterns(pattern);
3423         if (ret < 0) {
3424                 DPAA2_PMD_ERR(
3425                         "Invalid pattern list is given\n");
3426                 rte_flow_error_set(error, EPERM,
3427                            RTE_FLOW_ERROR_TYPE_ITEM,
3428                            pattern, "invalid");
3429                 goto not_valid_params;
3430         }
3431         /* Verify input action list */
3432         ret = dpaa2_dev_verify_actions(actions);
3433         if (ret < 0) {
3434                 DPAA2_PMD_ERR(
3435                         "Invalid action list is given\n");
3436                 rte_flow_error_set(error, EPERM,
3437                            RTE_FLOW_ERROR_TYPE_ACTION,
3438                            actions, "invalid");
3439                 goto not_valid_params;
3440         }
3441 not_valid_params:
3442         return ret;
3443 }
3444
3445 static
3446 struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev,
3447                                    const struct rte_flow_attr *attr,
3448                                    const struct rte_flow_item pattern[],
3449                                    const struct rte_flow_action actions[],
3450                                    struct rte_flow_error *error)
3451 {
3452         struct rte_flow *flow = NULL;
3453         size_t key_iova = 0, mask_iova = 0;
3454         int ret;
3455
3456         flow = rte_zmalloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE);
3457         if (!flow) {
3458                 DPAA2_PMD_ERR("Failure to allocate memory for flow");
3459                 goto mem_failure;
3460         }
3461         /* Allocate DMA'ble memory to write the rules */
3462         key_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3463         if (!key_iova) {
3464                 DPAA2_PMD_ERR(
3465                         "Memory allocation failure for rule configuration\n");
3466                 goto mem_failure;
3467         }
3468         mask_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3469         if (!mask_iova) {
3470                 DPAA2_PMD_ERR(
3471                         "Memory allocation failure for rule configuration\n");
3472                 goto mem_failure;
3473         }
3474
3475         flow->qos_rule.key_iova = key_iova;
3476         flow->qos_rule.mask_iova = mask_iova;
3477
3478         /* Allocate DMA'ble memory to write the rules */
3479         key_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3480         if (!key_iova) {
3481                 DPAA2_PMD_ERR(
3482                         "Memory allocation failure for rule configuration\n");
3483                 goto mem_failure;
3484         }
3485         mask_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3486         if (!mask_iova) {
3487                 DPAA2_PMD_ERR(
3488                         "Memory allocation failure for rule configuration\n");
3489                 goto mem_failure;
3490         }
3491
3492         flow->fs_rule.key_iova = key_iova;
3493         flow->fs_rule.mask_iova = mask_iova;
3494
3495         flow->ipaddr_rule.ipaddr_type = FLOW_NONE_IPADDR;
3496         flow->ipaddr_rule.qos_ipsrc_offset =
3497                 IP_ADDRESS_OFFSET_INVALID;
3498         flow->ipaddr_rule.qos_ipdst_offset =
3499                 IP_ADDRESS_OFFSET_INVALID;
3500         flow->ipaddr_rule.fs_ipsrc_offset =
3501                 IP_ADDRESS_OFFSET_INVALID;
3502         flow->ipaddr_rule.fs_ipdst_offset =
3503                 IP_ADDRESS_OFFSET_INVALID;
3504
3505         switch (dpaa2_filter_type) {
3506         case RTE_ETH_FILTER_GENERIC:
3507                 ret = dpaa2_generic_flow_set(flow, dev, attr, pattern,
3508                                              actions, error);
3509                 if (ret < 0) {
3510                         if (error->type > RTE_FLOW_ERROR_TYPE_ACTION)
3511                                 rte_flow_error_set(error, EPERM,
3512                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3513                                                 attr, "unknown");
3514                         DPAA2_PMD_ERR(
3515                         "Failure to create flow, return code (%d)", ret);
3516                         goto creation_error;
3517                 }
3518                 break;
3519         default:
3520                 DPAA2_PMD_ERR("Filter type (%d) not supported",
3521                 dpaa2_filter_type);
3522                 break;
3523         }
3524
3525         return flow;
3526 mem_failure:
3527         rte_flow_error_set(error, EPERM,
3528                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3529                            NULL, "memory alloc");
3530 creation_error:
3531         rte_free((void *)flow);
3532         rte_free((void *)key_iova);
3533         rte_free((void *)mask_iova);
3534
3535         return NULL;
3536 }
3537
3538 static
3539 int dpaa2_flow_destroy(struct rte_eth_dev *dev,
3540                        struct rte_flow *flow,
3541                        struct rte_flow_error *error)
3542 {
3543         int ret = 0;
3544         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3545         struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
3546
3547         switch (flow->action) {
3548         case RTE_FLOW_ACTION_TYPE_QUEUE:
3549                 /* Remove entry from QoS table first */
3550                 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
3551                                            &flow->qos_rule);
3552                 if (ret < 0) {
3553                         DPAA2_PMD_ERR(
3554                                 "Error in adding entry to QoS table(%d)", ret);
3555                         goto error;
3556                 }
3557
3558                 /* Then remove entry from FS table */
3559                 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token,
3560                                            flow->tc_id, &flow->fs_rule);
3561                 if (ret < 0) {
3562                         DPAA2_PMD_ERR(
3563                                 "Error in entry addition in FS table(%d)", ret);
3564                         goto error;
3565                 }
3566                 break;
3567         case RTE_FLOW_ACTION_TYPE_RSS:
3568                 ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
3569                                            &flow->qos_rule);
3570                 if (ret < 0) {
3571                         DPAA2_PMD_ERR(
3572                         "Error in entry addition in QoS table(%d)", ret);
3573                         goto error;
3574                 }
3575                 break;
3576         default:
3577                 DPAA2_PMD_ERR(
3578                 "Action type (%d) is not supported", flow->action);
3579                 ret = -ENOTSUP;
3580                 break;
3581         }
3582
3583         LIST_REMOVE(flow, next);
3584         rte_free((void *)(size_t)flow->qos_rule.key_iova);
3585         rte_free((void *)(size_t)flow->qos_rule.mask_iova);
3586         rte_free((void *)(size_t)flow->fs_rule.key_iova);
3587         rte_free((void *)(size_t)flow->fs_rule.mask_iova);
3588         /* Now free the flow */
3589         rte_free(flow);
3590
3591 error:
3592         if (ret)
3593                 rte_flow_error_set(error, EPERM,
3594                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3595                                    NULL, "unknown");
3596         return ret;
3597 }
3598
3599 /**
3600  * Destroy user-configured flow rules.
3601  *
3602  * This function skips internal flows rules.
3603  *
3604  * @see rte_flow_flush()
3605  * @see rte_flow_ops
3606  */
3607 static int
3608 dpaa2_flow_flush(struct rte_eth_dev *dev,
3609                 struct rte_flow_error *error)
3610 {
3611         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3612         struct rte_flow *flow = LIST_FIRST(&priv->flows);
3613
3614         while (flow) {
3615                 struct rte_flow *next = LIST_NEXT(flow, next);
3616
3617                 dpaa2_flow_destroy(dev, flow, error);
3618                 flow = next;
3619         }
3620         return 0;
3621 }
3622
3623 static int
3624 dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused,
3625                 struct rte_flow *flow __rte_unused,
3626                 const struct rte_flow_action *actions __rte_unused,
3627                 void *data __rte_unused,
3628                 struct rte_flow_error *error __rte_unused)
3629 {
3630         return 0;
3631 }
3632
3633 /**
3634  * Clean up all flow rules.
3635  *
3636  * Unlike dpaa2_flow_flush(), this function takes care of all remaining flow
3637  * rules regardless of whether they are internal or user-configured.
3638  *
3639  * @param priv
3640  *   Pointer to private structure.
3641  */
3642 void
3643 dpaa2_flow_clean(struct rte_eth_dev *dev)
3644 {
3645         struct rte_flow *flow;
3646         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3647
3648         while ((flow = LIST_FIRST(&priv->flows)))
3649                 dpaa2_flow_destroy(dev, flow, NULL);
3650 }
3651
3652 const struct rte_flow_ops dpaa2_flow_ops = {
3653         .create = dpaa2_flow_create,
3654         .validate = dpaa2_flow_validate,
3655         .destroy = dpaa2_flow_destroy,
3656         .flush  = dpaa2_flow_flush,
3657         .query  = dpaa2_flow_query,
3658 };