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