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