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