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