cff01c448504abbfaa850e6c450a7ec3f346b0c1
[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                 if (priv->num_rx_tc > 1) {
2876                         ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW,
2877                                         priv->token, &curr->qos_rule);
2878                         if (ret) {
2879                                 DPAA2_PMD_ERR("Qos entry remove failed.");
2880                                 return -1;
2881                         }
2882                 }
2883
2884                 extend = -1;
2885
2886                 if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {
2887                         RTE_ASSERT(qos_ipsrc_offset >=
2888                                 curr->ipaddr_rule.qos_ipsrc_offset);
2889                         extend1 = qos_ipsrc_offset -
2890                                 curr->ipaddr_rule.qos_ipsrc_offset;
2891                         if (extend >= 0)
2892                                 RTE_ASSERT(extend == extend1);
2893                         else
2894                                 extend = extend1;
2895
2896                         RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
2897                                 (size == NH_FLD_IPV6_ADDR_SIZE));
2898
2899                         memcpy(ipsrc_key,
2900                                 (char *)(size_t)curr->qos_rule.key_iova +
2901                                 curr->ipaddr_rule.qos_ipsrc_offset,
2902                                 size);
2903                         memset((char *)(size_t)curr->qos_rule.key_iova +
2904                                 curr->ipaddr_rule.qos_ipsrc_offset,
2905                                 0, size);
2906
2907                         memcpy(ipsrc_mask,
2908                                 (char *)(size_t)curr->qos_rule.mask_iova +
2909                                 curr->ipaddr_rule.qos_ipsrc_offset,
2910                                 size);
2911                         memset((char *)(size_t)curr->qos_rule.mask_iova +
2912                                 curr->ipaddr_rule.qos_ipsrc_offset,
2913                                 0, size);
2914
2915                         curr->ipaddr_rule.qos_ipsrc_offset = qos_ipsrc_offset;
2916                 }
2917
2918                 if (curr->ipaddr_rule.qos_ipdst_offset >= 0) {
2919                         RTE_ASSERT(qos_ipdst_offset >=
2920                                 curr->ipaddr_rule.qos_ipdst_offset);
2921                         extend1 = qos_ipdst_offset -
2922                                 curr->ipaddr_rule.qos_ipdst_offset;
2923                         if (extend >= 0)
2924                                 RTE_ASSERT(extend == extend1);
2925                         else
2926                                 extend = extend1;
2927
2928                         RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
2929                                 (size == NH_FLD_IPV6_ADDR_SIZE));
2930
2931                         memcpy(ipdst_key,
2932                                 (char *)(size_t)curr->qos_rule.key_iova +
2933                                 curr->ipaddr_rule.qos_ipdst_offset,
2934                                 size);
2935                         memset((char *)(size_t)curr->qos_rule.key_iova +
2936                                 curr->ipaddr_rule.qos_ipdst_offset,
2937                                 0, size);
2938
2939                         memcpy(ipdst_mask,
2940                                 (char *)(size_t)curr->qos_rule.mask_iova +
2941                                 curr->ipaddr_rule.qos_ipdst_offset,
2942                                 size);
2943                         memset((char *)(size_t)curr->qos_rule.mask_iova +
2944                                 curr->ipaddr_rule.qos_ipdst_offset,
2945                                 0, size);
2946
2947                         curr->ipaddr_rule.qos_ipdst_offset = qos_ipdst_offset;
2948                 }
2949
2950                 if (curr->ipaddr_rule.qos_ipsrc_offset >= 0) {
2951                         RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
2952                                 (size == NH_FLD_IPV6_ADDR_SIZE));
2953                         memcpy((char *)(size_t)curr->qos_rule.key_iova +
2954                                 curr->ipaddr_rule.qos_ipsrc_offset,
2955                                 ipsrc_key,
2956                                 size);
2957                         memcpy((char *)(size_t)curr->qos_rule.mask_iova +
2958                                 curr->ipaddr_rule.qos_ipsrc_offset,
2959                                 ipsrc_mask,
2960                                 size);
2961                 }
2962                 if (curr->ipaddr_rule.qos_ipdst_offset >= 0) {
2963                         RTE_ASSERT((size == NH_FLD_IPV4_ADDR_SIZE) ||
2964                                 (size == NH_FLD_IPV6_ADDR_SIZE));
2965                         memcpy((char *)(size_t)curr->qos_rule.key_iova +
2966                                 curr->ipaddr_rule.qos_ipdst_offset,
2967                                 ipdst_key,
2968                                 size);
2969                         memcpy((char *)(size_t)curr->qos_rule.mask_iova +
2970                                 curr->ipaddr_rule.qos_ipdst_offset,
2971                                 ipdst_mask,
2972                                 size);
2973                 }
2974
2975                 if (extend >= 0)
2976                         curr->qos_real_key_size += extend;
2977
2978                 curr->qos_rule.key_size = FIXED_ENTRY_SIZE;
2979
2980                 dpaa2_flow_qos_entry_log("Start update", curr, qos_index);
2981
2982                 if (priv->num_rx_tc > 1) {
2983                         ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
2984                                         priv->token, &curr->qos_rule,
2985                                         curr->tc_id, qos_index,
2986                                         0, 0);
2987                         if (ret) {
2988                                 DPAA2_PMD_ERR("Qos entry update failed.");
2989                                 return -1;
2990                         }
2991                 }
2992
2993                 if (curr->action != RTE_FLOW_ACTION_TYPE_QUEUE) {
2994                         curr = LIST_NEXT(curr, next);
2995                         continue;
2996                 }
2997
2998                 dpaa2_flow_fs_entry_log("Before update", curr);
2999                 extend = -1;
3000
3001                 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW,
3002                                 priv->token, curr->tc_id, &curr->fs_rule);
3003                 if (ret) {
3004                         DPAA2_PMD_ERR("FS entry remove failed.");
3005                         return -1;
3006                 }
3007
3008                 if (curr->ipaddr_rule.fs_ipsrc_offset >= 0 &&
3009                         tc_id == curr->tc_id) {
3010                         RTE_ASSERT(fs_ipsrc_offset >=
3011                                 curr->ipaddr_rule.fs_ipsrc_offset);
3012                         extend1 = fs_ipsrc_offset -
3013                                 curr->ipaddr_rule.fs_ipsrc_offset;
3014                         if (extend >= 0)
3015                                 RTE_ASSERT(extend == extend1);
3016                         else
3017                                 extend = extend1;
3018
3019                         memcpy(ipsrc_key,
3020                                 (char *)(size_t)curr->fs_rule.key_iova +
3021                                 curr->ipaddr_rule.fs_ipsrc_offset,
3022                                 size);
3023                         memset((char *)(size_t)curr->fs_rule.key_iova +
3024                                 curr->ipaddr_rule.fs_ipsrc_offset,
3025                                 0, size);
3026
3027                         memcpy(ipsrc_mask,
3028                                 (char *)(size_t)curr->fs_rule.mask_iova +
3029                                 curr->ipaddr_rule.fs_ipsrc_offset,
3030                                 size);
3031                         memset((char *)(size_t)curr->fs_rule.mask_iova +
3032                                 curr->ipaddr_rule.fs_ipsrc_offset,
3033                                 0, size);
3034
3035                         curr->ipaddr_rule.fs_ipsrc_offset = fs_ipsrc_offset;
3036                 }
3037
3038                 if (curr->ipaddr_rule.fs_ipdst_offset >= 0 &&
3039                         tc_id == curr->tc_id) {
3040                         RTE_ASSERT(fs_ipdst_offset >=
3041                                 curr->ipaddr_rule.fs_ipdst_offset);
3042                         extend1 = fs_ipdst_offset -
3043                                 curr->ipaddr_rule.fs_ipdst_offset;
3044                         if (extend >= 0)
3045                                 RTE_ASSERT(extend == extend1);
3046                         else
3047                                 extend = extend1;
3048
3049                         memcpy(ipdst_key,
3050                                 (char *)(size_t)curr->fs_rule.key_iova +
3051                                 curr->ipaddr_rule.fs_ipdst_offset,
3052                                 size);
3053                         memset((char *)(size_t)curr->fs_rule.key_iova +
3054                                 curr->ipaddr_rule.fs_ipdst_offset,
3055                                 0, size);
3056
3057                         memcpy(ipdst_mask,
3058                                 (char *)(size_t)curr->fs_rule.mask_iova +
3059                                 curr->ipaddr_rule.fs_ipdst_offset,
3060                                 size);
3061                         memset((char *)(size_t)curr->fs_rule.mask_iova +
3062                                 curr->ipaddr_rule.fs_ipdst_offset,
3063                                 0, size);
3064
3065                         curr->ipaddr_rule.fs_ipdst_offset = fs_ipdst_offset;
3066                 }
3067
3068                 if (curr->ipaddr_rule.fs_ipsrc_offset >= 0) {
3069                         memcpy((char *)(size_t)curr->fs_rule.key_iova +
3070                                 curr->ipaddr_rule.fs_ipsrc_offset,
3071                                 ipsrc_key,
3072                                 size);
3073                         memcpy((char *)(size_t)curr->fs_rule.mask_iova +
3074                                 curr->ipaddr_rule.fs_ipsrc_offset,
3075                                 ipsrc_mask,
3076                                 size);
3077                 }
3078                 if (curr->ipaddr_rule.fs_ipdst_offset >= 0) {
3079                         memcpy((char *)(size_t)curr->fs_rule.key_iova +
3080                                 curr->ipaddr_rule.fs_ipdst_offset,
3081                                 ipdst_key,
3082                                 size);
3083                         memcpy((char *)(size_t)curr->fs_rule.mask_iova +
3084                                 curr->ipaddr_rule.fs_ipdst_offset,
3085                                 ipdst_mask,
3086                                 size);
3087                 }
3088
3089                 if (extend >= 0)
3090                         curr->fs_real_key_size += extend;
3091                 curr->fs_rule.key_size = FIXED_ENTRY_SIZE;
3092
3093                 dpaa2_flow_fs_entry_log("Start update", curr);
3094
3095                 ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW,
3096                                 priv->token, curr->tc_id, curr->tc_index,
3097                                 &curr->fs_rule, &curr->action_cfg);
3098                 if (ret) {
3099                         DPAA2_PMD_ERR("FS entry update failed.");
3100                         return -1;
3101                 }
3102
3103                 curr = LIST_NEXT(curr, next);
3104         }
3105
3106         return 0;
3107 }
3108
3109 static inline int
3110 dpaa2_flow_verify_attr(
3111         struct dpaa2_dev_priv *priv,
3112         const struct rte_flow_attr *attr)
3113 {
3114         struct rte_flow *curr = LIST_FIRST(&priv->flows);
3115
3116         while (curr) {
3117                 if (curr->tc_id == attr->group &&
3118                         curr->tc_index == attr->priority) {
3119                         DPAA2_PMD_ERR(
3120                                 "Flow with group %d and priority %d already exists.",
3121                                 attr->group, attr->priority);
3122
3123                         return -1;
3124                 }
3125                 curr = LIST_NEXT(curr, next);
3126         }
3127
3128         return 0;
3129 }
3130
3131 static inline int
3132 dpaa2_flow_verify_action(
3133         struct dpaa2_dev_priv *priv,
3134         const struct rte_flow_attr *attr,
3135         const struct rte_flow_action actions[])
3136 {
3137         int end_of_list = 0, i, j = 0;
3138         const struct rte_flow_action_queue *dest_queue;
3139         const struct rte_flow_action_rss *rss_conf;
3140         struct dpaa2_queue *rxq;
3141
3142         while (!end_of_list) {
3143                 switch (actions[j].type) {
3144                 case RTE_FLOW_ACTION_TYPE_QUEUE:
3145                         dest_queue = (const struct rte_flow_action_queue *)
3146                                         (actions[j].conf);
3147                         rxq = priv->rx_vq[dest_queue->index];
3148                         if (attr->group != rxq->tc_index) {
3149                                 DPAA2_PMD_ERR(
3150                                         "RXQ[%d] does not belong to the group %d",
3151                                         dest_queue->index, attr->group);
3152
3153                                 return -1;
3154                         }
3155                         break;
3156                 case RTE_FLOW_ACTION_TYPE_RSS:
3157                         rss_conf = (const struct rte_flow_action_rss *)
3158                                         (actions[j].conf);
3159                         if (rss_conf->queue_num > priv->dist_queues) {
3160                                 DPAA2_PMD_ERR(
3161                                         "RSS number exceeds the distrbution size");
3162                                 return -ENOTSUP;
3163                         }
3164                         for (i = 0; i < (int)rss_conf->queue_num; i++) {
3165                                 if (rss_conf->queue[i] >= priv->nb_rx_queues) {
3166                                         DPAA2_PMD_ERR(
3167                                                 "RSS queue index exceeds the number of RXQs");
3168                                         return -ENOTSUP;
3169                                 }
3170                                 rxq = priv->rx_vq[rss_conf->queue[i]];
3171                                 if (rxq->tc_index != attr->group) {
3172                                         DPAA2_PMD_ERR(
3173                                                 "Queue/Group combination are not supported\n");
3174                                         return -ENOTSUP;
3175                                 }
3176                         }
3177
3178                         break;
3179                 case RTE_FLOW_ACTION_TYPE_END:
3180                         end_of_list = 1;
3181                         break;
3182                 default:
3183                         DPAA2_PMD_ERR("Invalid action type");
3184                         return -ENOTSUP;
3185                 }
3186                 j++;
3187         }
3188
3189         return 0;
3190 }
3191
3192 static int
3193 dpaa2_generic_flow_set(struct rte_flow *flow,
3194                        struct rte_eth_dev *dev,
3195                        const struct rte_flow_attr *attr,
3196                        const struct rte_flow_item pattern[],
3197                        const struct rte_flow_action actions[],
3198                        struct rte_flow_error *error)
3199 {
3200         const struct rte_flow_action_queue *dest_queue;
3201         const struct rte_flow_action_rss *rss_conf;
3202         int is_keycfg_configured = 0, end_of_list = 0;
3203         int ret = 0, i = 0, j = 0;
3204         struct dpni_rx_tc_dist_cfg tc_cfg;
3205         struct dpni_qos_tbl_cfg qos_cfg;
3206         struct dpni_fs_action_cfg action;
3207         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3208         struct dpaa2_queue *rxq;
3209         struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
3210         size_t param;
3211         struct rte_flow *curr = LIST_FIRST(&priv->flows);
3212         uint16_t qos_index;
3213
3214         ret = dpaa2_flow_verify_attr(priv, attr);
3215         if (ret)
3216                 return ret;
3217
3218         ret = dpaa2_flow_verify_action(priv, attr, actions);
3219         if (ret)
3220                 return ret;
3221
3222         /* Parse pattern list to get the matching parameters */
3223         while (!end_of_list) {
3224                 switch (pattern[i].type) {
3225                 case RTE_FLOW_ITEM_TYPE_ETH:
3226                         ret = dpaa2_configure_flow_eth(flow,
3227                                         dev, attr, &pattern[i], actions, error,
3228                                         &is_keycfg_configured);
3229                         if (ret) {
3230                                 DPAA2_PMD_ERR("ETH flow configuration failed!");
3231                                 return ret;
3232                         }
3233                         break;
3234                 case RTE_FLOW_ITEM_TYPE_VLAN:
3235                         ret = dpaa2_configure_flow_vlan(flow,
3236                                         dev, attr, &pattern[i], actions, error,
3237                                         &is_keycfg_configured);
3238                         if (ret) {
3239                                 DPAA2_PMD_ERR("vLan flow configuration failed!");
3240                                 return ret;
3241                         }
3242                         break;
3243                 case RTE_FLOW_ITEM_TYPE_IPV4:
3244                 case RTE_FLOW_ITEM_TYPE_IPV6:
3245                         ret = dpaa2_configure_flow_generic_ip(flow,
3246                                         dev, attr, &pattern[i], actions, error,
3247                                         &is_keycfg_configured);
3248                         if (ret) {
3249                                 DPAA2_PMD_ERR("IP flow configuration failed!");
3250                                 return ret;
3251                         }
3252                         break;
3253                 case RTE_FLOW_ITEM_TYPE_ICMP:
3254                         ret = dpaa2_configure_flow_icmp(flow,
3255                                         dev, attr, &pattern[i], actions, error,
3256                                         &is_keycfg_configured);
3257                         if (ret) {
3258                                 DPAA2_PMD_ERR("ICMP flow configuration failed!");
3259                                 return ret;
3260                         }
3261                         break;
3262                 case RTE_FLOW_ITEM_TYPE_UDP:
3263                         ret = dpaa2_configure_flow_udp(flow,
3264                                         dev, attr, &pattern[i], actions, error,
3265                                         &is_keycfg_configured);
3266                         if (ret) {
3267                                 DPAA2_PMD_ERR("UDP flow configuration failed!");
3268                                 return ret;
3269                         }
3270                         break;
3271                 case RTE_FLOW_ITEM_TYPE_TCP:
3272                         ret = dpaa2_configure_flow_tcp(flow,
3273                                         dev, attr, &pattern[i], actions, error,
3274                                         &is_keycfg_configured);
3275                         if (ret) {
3276                                 DPAA2_PMD_ERR("TCP flow configuration failed!");
3277                                 return ret;
3278                         }
3279                         break;
3280                 case RTE_FLOW_ITEM_TYPE_SCTP:
3281                         ret = dpaa2_configure_flow_sctp(flow,
3282                                         dev, attr, &pattern[i], actions, error,
3283                                         &is_keycfg_configured);
3284                         if (ret) {
3285                                 DPAA2_PMD_ERR("SCTP flow configuration failed!");
3286                                 return ret;
3287                         }
3288                         break;
3289                 case RTE_FLOW_ITEM_TYPE_GRE:
3290                         ret = dpaa2_configure_flow_gre(flow,
3291                                         dev, attr, &pattern[i], actions, error,
3292                                         &is_keycfg_configured);
3293                         if (ret) {
3294                                 DPAA2_PMD_ERR("GRE flow configuration failed!");
3295                                 return ret;
3296                         }
3297                         break;
3298                 case RTE_FLOW_ITEM_TYPE_END:
3299                         end_of_list = 1;
3300                         break; /*End of List*/
3301                 default:
3302                         DPAA2_PMD_ERR("Invalid action type");
3303                         ret = -ENOTSUP;
3304                         break;
3305                 }
3306                 i++;
3307         }
3308
3309         /* Let's parse action on matching traffic */
3310         end_of_list = 0;
3311         while (!end_of_list) {
3312                 switch (actions[j].type) {
3313                 case RTE_FLOW_ACTION_TYPE_QUEUE:
3314                         dest_queue =
3315                                 (const struct rte_flow_action_queue *)(actions[j].conf);
3316                         rxq = priv->rx_vq[dest_queue->index];
3317                         flow->action = RTE_FLOW_ACTION_TYPE_QUEUE;
3318                         memset(&action, 0, sizeof(struct dpni_fs_action_cfg));
3319                         action.flow_id = rxq->flow_id;
3320
3321                         /* Configure FS table first*/
3322                         if (is_keycfg_configured & DPAA2_FS_TABLE_RECONFIGURE) {
3323                                 dpaa2_flow_fs_table_extracts_log(priv, flow->tc_id);
3324                                 if (dpkg_prepare_key_cfg(
3325                                 &priv->extract.tc_key_extract[flow->tc_id].dpkg,
3326                                 (uint8_t *)(size_t)priv->extract
3327                                 .tc_extract_param[flow->tc_id]) < 0) {
3328                                         DPAA2_PMD_ERR(
3329                                         "Unable to prepare extract parameters");
3330                                         return -1;
3331                                 }
3332
3333                                 memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
3334                                 tc_cfg.dist_size = priv->nb_rx_queues / priv->num_rx_tc;
3335                                 tc_cfg.dist_mode = DPNI_DIST_MODE_FS;
3336                                 tc_cfg.key_cfg_iova =
3337                                         (uint64_t)priv->extract.tc_extract_param[flow->tc_id];
3338                                 tc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP;
3339                                 tc_cfg.fs_cfg.keep_entries = true;
3340                                 ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW,
3341                                                          priv->token,
3342                                                          flow->tc_id, &tc_cfg);
3343                                 if (ret < 0) {
3344                                         DPAA2_PMD_ERR(
3345                                         "Distribution cannot be configured.(%d)"
3346                                         , ret);
3347                                         return -1;
3348                                 }
3349                         }
3350
3351                         /* Configure QoS table then.*/
3352                         if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
3353                                 dpaa2_flow_qos_table_extracts_log(priv);
3354                                 if (dpkg_prepare_key_cfg(
3355                                         &priv->extract.qos_key_extract.dpkg,
3356                                         (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
3357                                         DPAA2_PMD_ERR(
3358                                                 "Unable to prepare extract parameters");
3359                                         return -1;
3360                                 }
3361
3362                                 memset(&qos_cfg, 0, sizeof(struct dpni_qos_tbl_cfg));
3363                                 qos_cfg.discard_on_miss = false;
3364                                 qos_cfg.default_tc = 0;
3365                                 qos_cfg.keep_entries = true;
3366                                 qos_cfg.key_cfg_iova =
3367                                         (size_t)priv->extract.qos_extract_param;
3368                                 /* QoS table is effecitive for multiple TCs.*/
3369                                 if (priv->num_rx_tc > 1) {
3370                                         ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
3371                                                 priv->token, &qos_cfg);
3372                                         if (ret < 0) {
3373                                                 DPAA2_PMD_ERR(
3374                                                 "RSS QoS table can not be configured(%d)\n",
3375                                                         ret);
3376                                                 return -1;
3377                                         }
3378                                 }
3379                         }
3380
3381                         flow->qos_real_key_size = priv->extract
3382                                 .qos_key_extract.key_info.key_total_size;
3383                         if (flow->ipaddr_rule.ipaddr_type == FLOW_IPV4_ADDR) {
3384                                 if (flow->ipaddr_rule.qos_ipdst_offset >=
3385                                         flow->ipaddr_rule.qos_ipsrc_offset) {
3386                                         flow->qos_real_key_size =
3387                                                 flow->ipaddr_rule.qos_ipdst_offset +
3388                                                 NH_FLD_IPV4_ADDR_SIZE;
3389                                 } else {
3390                                         flow->qos_real_key_size =
3391                                                 flow->ipaddr_rule.qos_ipsrc_offset +
3392                                                 NH_FLD_IPV4_ADDR_SIZE;
3393                                 }
3394                         } else if (flow->ipaddr_rule.ipaddr_type ==
3395                                 FLOW_IPV6_ADDR) {
3396                                 if (flow->ipaddr_rule.qos_ipdst_offset >=
3397                                         flow->ipaddr_rule.qos_ipsrc_offset) {
3398                                         flow->qos_real_key_size =
3399                                                 flow->ipaddr_rule.qos_ipdst_offset +
3400                                                 NH_FLD_IPV6_ADDR_SIZE;
3401                                 } else {
3402                                         flow->qos_real_key_size =
3403                                                 flow->ipaddr_rule.qos_ipsrc_offset +
3404                                                 NH_FLD_IPV6_ADDR_SIZE;
3405                                 }
3406                         }
3407
3408                         /* QoS entry added is only effective for multiple TCs.*/
3409                         if (priv->num_rx_tc > 1) {
3410                                 qos_index = flow->tc_id * priv->fs_entries +
3411                                         flow->tc_index;
3412                                 if (qos_index >= priv->qos_entries) {
3413                                         DPAA2_PMD_ERR("QoS table with %d entries full",
3414                                                 priv->qos_entries);
3415                                         return -1;
3416                                 }
3417                                 flow->qos_rule.key_size = FIXED_ENTRY_SIZE;
3418
3419                                 dpaa2_flow_qos_entry_log("Start add", flow, qos_index);
3420
3421                                 ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW,
3422                                                 priv->token, &flow->qos_rule,
3423                                                 flow->tc_id, qos_index,
3424                                                 0, 0);
3425                                 if (ret < 0) {
3426                                         DPAA2_PMD_ERR(
3427                                                 "Error in addnig entry to QoS table(%d)", ret);
3428                                         return ret;
3429                                 }
3430                         }
3431
3432                         if (flow->tc_index >= priv->fs_entries) {
3433                                 DPAA2_PMD_ERR("FS table with %d entries full",
3434                                         priv->fs_entries);
3435                                 return -1;
3436                         }
3437
3438                         flow->fs_real_key_size =
3439                                 priv->extract.tc_key_extract[flow->tc_id]
3440                                 .key_info.key_total_size;
3441
3442                         if (flow->ipaddr_rule.ipaddr_type ==
3443                                 FLOW_IPV4_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_IPV4_ADDR_SIZE;
3449                                 } else {
3450                                         flow->fs_real_key_size =
3451                                                 flow->ipaddr_rule.fs_ipsrc_offset +
3452                                                 NH_FLD_IPV4_ADDR_SIZE;
3453                                 }
3454                         } else if (flow->ipaddr_rule.ipaddr_type ==
3455                                 FLOW_IPV6_ADDR) {
3456                                 if (flow->ipaddr_rule.fs_ipdst_offset >=
3457                                         flow->ipaddr_rule.fs_ipsrc_offset) {
3458                                         flow->fs_real_key_size =
3459                                                 flow->ipaddr_rule.fs_ipdst_offset +
3460                                                 NH_FLD_IPV6_ADDR_SIZE;
3461                                 } else {
3462                                         flow->fs_real_key_size =
3463                                                 flow->ipaddr_rule.fs_ipsrc_offset +
3464                                                 NH_FLD_IPV6_ADDR_SIZE;
3465                                 }
3466                         }
3467
3468                         flow->fs_rule.key_size = FIXED_ENTRY_SIZE;
3469
3470                         dpaa2_flow_fs_entry_log("Start add", flow);
3471
3472                         ret = dpni_add_fs_entry(dpni, CMD_PRI_LOW, priv->token,
3473                                                 flow->tc_id, flow->tc_index,
3474                                                 &flow->fs_rule, &action);
3475                         if (ret < 0) {
3476                                 DPAA2_PMD_ERR(
3477                                 "Error in adding entry to FS table(%d)", ret);
3478                                 return ret;
3479                         }
3480                         memcpy(&flow->action_cfg, &action,
3481                                 sizeof(struct dpni_fs_action_cfg));
3482                         break;
3483                 case RTE_FLOW_ACTION_TYPE_RSS:
3484                         rss_conf = (const struct rte_flow_action_rss *)(actions[j].conf);
3485
3486                         flow->action = RTE_FLOW_ACTION_TYPE_RSS;
3487                         ret = dpaa2_distset_to_dpkg_profile_cfg(rss_conf->types,
3488                                         &priv->extract.tc_key_extract[flow->tc_id].dpkg);
3489                         if (ret < 0) {
3490                                 DPAA2_PMD_ERR(
3491                                 "unable to set flow distribution.please check queue config\n");
3492                                 return ret;
3493                         }
3494
3495                         /* Allocate DMA'ble memory to write the rules */
3496                         param = (size_t)rte_malloc(NULL, 256, 64);
3497                         if (!param) {
3498                                 DPAA2_PMD_ERR("Memory allocation failure\n");
3499                                 return -1;
3500                         }
3501
3502                         if (dpkg_prepare_key_cfg(
3503                                 &priv->extract.tc_key_extract[flow->tc_id].dpkg,
3504                                 (uint8_t *)param) < 0) {
3505                                 DPAA2_PMD_ERR(
3506                                 "Unable to prepare extract parameters");
3507                                 rte_free((void *)param);
3508                                 return -1;
3509                         }
3510
3511                         memset(&tc_cfg, 0, sizeof(struct dpni_rx_tc_dist_cfg));
3512                         tc_cfg.dist_size = rss_conf->queue_num;
3513                         tc_cfg.dist_mode = DPNI_DIST_MODE_HASH;
3514                         tc_cfg.key_cfg_iova = (size_t)param;
3515                         tc_cfg.fs_cfg.miss_action = DPNI_FS_MISS_DROP;
3516
3517                         ret = dpni_set_rx_tc_dist(dpni, CMD_PRI_LOW,
3518                                                  priv->token, flow->tc_id,
3519                                                  &tc_cfg);
3520                         if (ret < 0) {
3521                                 DPAA2_PMD_ERR(
3522                                         "RSS FS table cannot be configured: %d\n",
3523                                         ret);
3524                                 rte_free((void *)param);
3525                                 return -1;
3526                         }
3527
3528                         rte_free((void *)param);
3529                         if (is_keycfg_configured & DPAA2_QOS_TABLE_RECONFIGURE) {
3530                                 if (dpkg_prepare_key_cfg(
3531                                         &priv->extract.qos_key_extract.dpkg,
3532                                         (uint8_t *)(size_t)priv->extract.qos_extract_param) < 0) {
3533                                         DPAA2_PMD_ERR(
3534                                         "Unable to prepare extract parameters");
3535                                         return -1;
3536                                 }
3537                                 memset(&qos_cfg, 0,
3538                                         sizeof(struct dpni_qos_tbl_cfg));
3539                                 qos_cfg.discard_on_miss = true;
3540                                 qos_cfg.keep_entries = true;
3541                                 qos_cfg.key_cfg_iova =
3542                                         (size_t)priv->extract.qos_extract_param;
3543                                 ret = dpni_set_qos_table(dpni, CMD_PRI_LOW,
3544                                                          priv->token, &qos_cfg);
3545                                 if (ret < 0) {
3546                                         DPAA2_PMD_ERR(
3547                                         "Distribution can't be configured %d\n",
3548                                         ret);
3549                                         return -1;
3550                                 }
3551                         }
3552
3553                         /* Add Rule into QoS table */
3554                         qos_index = flow->tc_id * priv->fs_entries +
3555                                 flow->tc_index;
3556                         if (qos_index >= priv->qos_entries) {
3557                                 DPAA2_PMD_ERR("QoS table with %d entries full",
3558                                         priv->qos_entries);
3559                                 return -1;
3560                         }
3561
3562                         flow->qos_real_key_size =
3563                           priv->extract.qos_key_extract.key_info.key_total_size;
3564                         flow->qos_rule.key_size = FIXED_ENTRY_SIZE;
3565                         ret = dpni_add_qos_entry(dpni, CMD_PRI_LOW, priv->token,
3566                                                 &flow->qos_rule, flow->tc_id,
3567                                                 qos_index, 0, 0);
3568                         if (ret < 0) {
3569                                 DPAA2_PMD_ERR(
3570                                 "Error in entry addition in QoS table(%d)",
3571                                 ret);
3572                                 return ret;
3573                         }
3574                         break;
3575                 case RTE_FLOW_ACTION_TYPE_END:
3576                         end_of_list = 1;
3577                         break;
3578                 default:
3579                         DPAA2_PMD_ERR("Invalid action type");
3580                         ret = -ENOTSUP;
3581                         break;
3582                 }
3583                 j++;
3584         }
3585
3586         if (!ret) {
3587                 if (is_keycfg_configured &
3588                         (DPAA2_QOS_TABLE_RECONFIGURE |
3589                         DPAA2_FS_TABLE_RECONFIGURE)) {
3590                         ret = dpaa2_flow_entry_update(priv, flow->tc_id);
3591                         if (ret) {
3592                                 DPAA2_PMD_ERR("Flow entry update failed.");
3593
3594                                 return -1;
3595                         }
3596                 }
3597                 /* New rules are inserted. */
3598                 if (!curr) {
3599                         LIST_INSERT_HEAD(&priv->flows, flow, next);
3600                 } else {
3601                         while (LIST_NEXT(curr, next))
3602                                 curr = LIST_NEXT(curr, next);
3603                         LIST_INSERT_AFTER(curr, flow, next);
3604                 }
3605         }
3606         return ret;
3607 }
3608
3609 static inline int
3610 dpaa2_dev_verify_attr(struct dpni_attr *dpni_attr,
3611                       const struct rte_flow_attr *attr)
3612 {
3613         int ret = 0;
3614
3615         if (unlikely(attr->group >= dpni_attr->num_rx_tcs)) {
3616                 DPAA2_PMD_ERR("Priority group is out of range\n");
3617                 ret = -ENOTSUP;
3618         }
3619         if (unlikely(attr->priority >= dpni_attr->fs_entries)) {
3620                 DPAA2_PMD_ERR("Priority within the group is out of range\n");
3621                 ret = -ENOTSUP;
3622         }
3623         if (unlikely(attr->egress)) {
3624                 DPAA2_PMD_ERR(
3625                         "Flow configuration is not supported on egress side\n");
3626                 ret = -ENOTSUP;
3627         }
3628         if (unlikely(!attr->ingress)) {
3629                 DPAA2_PMD_ERR("Ingress flag must be configured\n");
3630                 ret = -EINVAL;
3631         }
3632         return ret;
3633 }
3634
3635 static inline int
3636 dpaa2_dev_verify_patterns(const struct rte_flow_item pattern[])
3637 {
3638         unsigned int i, j, is_found = 0;
3639         int ret = 0;
3640
3641         for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {
3642                 for (i = 0; i < RTE_DIM(dpaa2_supported_pattern_type); i++) {
3643                         if (dpaa2_supported_pattern_type[i]
3644                                         == pattern[j].type) {
3645                                 is_found = 1;
3646                                 break;
3647                         }
3648                 }
3649                 if (!is_found) {
3650                         ret = -ENOTSUP;
3651                         break;
3652                 }
3653         }
3654         /* Lets verify other combinations of given pattern rules */
3655         for (j = 0; pattern[j].type != RTE_FLOW_ITEM_TYPE_END; j++) {
3656                 if (!pattern[j].spec) {
3657                         ret = -EINVAL;
3658                         break;
3659                 }
3660         }
3661
3662         return ret;
3663 }
3664
3665 static inline int
3666 dpaa2_dev_verify_actions(const struct rte_flow_action actions[])
3667 {
3668         unsigned int i, j, is_found = 0;
3669         int ret = 0;
3670
3671         for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
3672                 for (i = 0; i < RTE_DIM(dpaa2_supported_action_type); i++) {
3673                         if (dpaa2_supported_action_type[i] == actions[j].type) {
3674                                 is_found = 1;
3675                                 break;
3676                         }
3677                 }
3678                 if (!is_found) {
3679                         ret = -ENOTSUP;
3680                         break;
3681                 }
3682         }
3683         for (j = 0; actions[j].type != RTE_FLOW_ACTION_TYPE_END; j++) {
3684                 if (actions[j].type != RTE_FLOW_ACTION_TYPE_DROP &&
3685                                 !actions[j].conf)
3686                         ret = -EINVAL;
3687         }
3688         return ret;
3689 }
3690
3691 static
3692 int dpaa2_flow_validate(struct rte_eth_dev *dev,
3693                         const struct rte_flow_attr *flow_attr,
3694                         const struct rte_flow_item pattern[],
3695                         const struct rte_flow_action actions[],
3696                         struct rte_flow_error *error)
3697 {
3698         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3699         struct dpni_attr dpni_attr;
3700         struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
3701         uint16_t token = priv->token;
3702         int ret = 0;
3703
3704         memset(&dpni_attr, 0, sizeof(struct dpni_attr));
3705         ret = dpni_get_attributes(dpni, CMD_PRI_LOW, token, &dpni_attr);
3706         if (ret < 0) {
3707                 DPAA2_PMD_ERR(
3708                         "Failure to get dpni@%p attribute, err code  %d\n",
3709                         dpni, ret);
3710                 rte_flow_error_set(error, EPERM,
3711                            RTE_FLOW_ERROR_TYPE_ATTR,
3712                            flow_attr, "invalid");
3713                 return ret;
3714         }
3715
3716         /* Verify input attributes */
3717         ret = dpaa2_dev_verify_attr(&dpni_attr, flow_attr);
3718         if (ret < 0) {
3719                 DPAA2_PMD_ERR(
3720                         "Invalid attributes are given\n");
3721                 rte_flow_error_set(error, EPERM,
3722                            RTE_FLOW_ERROR_TYPE_ATTR,
3723                            flow_attr, "invalid");
3724                 goto not_valid_params;
3725         }
3726         /* Verify input pattern list */
3727         ret = dpaa2_dev_verify_patterns(pattern);
3728         if (ret < 0) {
3729                 DPAA2_PMD_ERR(
3730                         "Invalid pattern list is given\n");
3731                 rte_flow_error_set(error, EPERM,
3732                            RTE_FLOW_ERROR_TYPE_ITEM,
3733                            pattern, "invalid");
3734                 goto not_valid_params;
3735         }
3736         /* Verify input action list */
3737         ret = dpaa2_dev_verify_actions(actions);
3738         if (ret < 0) {
3739                 DPAA2_PMD_ERR(
3740                         "Invalid action list is given\n");
3741                 rte_flow_error_set(error, EPERM,
3742                            RTE_FLOW_ERROR_TYPE_ACTION,
3743                            actions, "invalid");
3744                 goto not_valid_params;
3745         }
3746 not_valid_params:
3747         return ret;
3748 }
3749
3750 static
3751 struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev,
3752                                    const struct rte_flow_attr *attr,
3753                                    const struct rte_flow_item pattern[],
3754                                    const struct rte_flow_action actions[],
3755                                    struct rte_flow_error *error)
3756 {
3757         struct rte_flow *flow = NULL;
3758         size_t key_iova = 0, mask_iova = 0;
3759         int ret;
3760
3761         dpaa2_flow_control_log =
3762                 getenv("DPAA2_FLOW_CONTROL_LOG");
3763
3764         flow = rte_zmalloc(NULL, sizeof(struct rte_flow), RTE_CACHE_LINE_SIZE);
3765         if (!flow) {
3766                 DPAA2_PMD_ERR("Failure to allocate memory for flow");
3767                 goto mem_failure;
3768         }
3769         /* Allocate DMA'ble memory to write the rules */
3770         key_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3771         if (!key_iova) {
3772                 DPAA2_PMD_ERR(
3773                         "Memory allocation failure for rule configuration\n");
3774                 goto mem_failure;
3775         }
3776         mask_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3777         if (!mask_iova) {
3778                 DPAA2_PMD_ERR(
3779                         "Memory allocation failure for rule configuration\n");
3780                 goto mem_failure;
3781         }
3782
3783         flow->qos_rule.key_iova = key_iova;
3784         flow->qos_rule.mask_iova = mask_iova;
3785
3786         /* Allocate DMA'ble memory to write the rules */
3787         key_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3788         if (!key_iova) {
3789                 DPAA2_PMD_ERR(
3790                         "Memory allocation failure for rule configuration\n");
3791                 goto mem_failure;
3792         }
3793         mask_iova = (size_t)rte_zmalloc(NULL, 256, 64);
3794         if (!mask_iova) {
3795                 DPAA2_PMD_ERR(
3796                         "Memory allocation failure for rule configuration\n");
3797                 goto mem_failure;
3798         }
3799
3800         flow->fs_rule.key_iova = key_iova;
3801         flow->fs_rule.mask_iova = mask_iova;
3802
3803         flow->ipaddr_rule.ipaddr_type = FLOW_NONE_IPADDR;
3804         flow->ipaddr_rule.qos_ipsrc_offset =
3805                 IP_ADDRESS_OFFSET_INVALID;
3806         flow->ipaddr_rule.qos_ipdst_offset =
3807                 IP_ADDRESS_OFFSET_INVALID;
3808         flow->ipaddr_rule.fs_ipsrc_offset =
3809                 IP_ADDRESS_OFFSET_INVALID;
3810         flow->ipaddr_rule.fs_ipdst_offset =
3811                 IP_ADDRESS_OFFSET_INVALID;
3812
3813         switch (dpaa2_filter_type) {
3814         case RTE_ETH_FILTER_GENERIC:
3815                 ret = dpaa2_generic_flow_set(flow, dev, attr, pattern,
3816                                              actions, error);
3817                 if (ret < 0) {
3818                         if (error->type > RTE_FLOW_ERROR_TYPE_ACTION)
3819                                 rte_flow_error_set(error, EPERM,
3820                                                 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3821                                                 attr, "unknown");
3822                         DPAA2_PMD_ERR(
3823                         "Failure to create flow, return code (%d)", ret);
3824                         goto creation_error;
3825                 }
3826                 break;
3827         default:
3828                 DPAA2_PMD_ERR("Filter type (%d) not supported",
3829                 dpaa2_filter_type);
3830                 break;
3831         }
3832
3833         return flow;
3834 mem_failure:
3835         rte_flow_error_set(error, EPERM,
3836                            RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3837                            NULL, "memory alloc");
3838 creation_error:
3839         rte_free((void *)flow);
3840         rte_free((void *)key_iova);
3841         rte_free((void *)mask_iova);
3842
3843         return NULL;
3844 }
3845
3846 static
3847 int dpaa2_flow_destroy(struct rte_eth_dev *dev,
3848                        struct rte_flow *flow,
3849                        struct rte_flow_error *error)
3850 {
3851         int ret = 0;
3852         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3853         struct fsl_mc_io *dpni = (struct fsl_mc_io *)priv->hw;
3854
3855         switch (flow->action) {
3856         case RTE_FLOW_ACTION_TYPE_QUEUE:
3857                 if (priv->num_rx_tc > 1) {
3858                         /* Remove entry from QoS table first */
3859                         ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
3860                                         &flow->qos_rule);
3861                         if (ret < 0) {
3862                                 DPAA2_PMD_ERR(
3863                                         "Error in removing entry from QoS table(%d)", ret);
3864                                 goto error;
3865                         }
3866                 }
3867
3868                 /* Then remove entry from FS table */
3869                 ret = dpni_remove_fs_entry(dpni, CMD_PRI_LOW, priv->token,
3870                                            flow->tc_id, &flow->fs_rule);
3871                 if (ret < 0) {
3872                         DPAA2_PMD_ERR(
3873                                 "Error in removing entry from FS table(%d)", ret);
3874                         goto error;
3875                 }
3876                 break;
3877         case RTE_FLOW_ACTION_TYPE_RSS:
3878                 if (priv->num_rx_tc > 1) {
3879                         ret = dpni_remove_qos_entry(dpni, CMD_PRI_LOW, priv->token,
3880                                         &flow->qos_rule);
3881                         if (ret < 0) {
3882                                 DPAA2_PMD_ERR(
3883                                         "Error in entry addition in QoS table(%d)", ret);
3884                                 goto error;
3885                         }
3886                 }
3887                 break;
3888         default:
3889                 DPAA2_PMD_ERR(
3890                 "Action type (%d) is not supported", flow->action);
3891                 ret = -ENOTSUP;
3892                 break;
3893         }
3894
3895         LIST_REMOVE(flow, next);
3896         rte_free((void *)(size_t)flow->qos_rule.key_iova);
3897         rte_free((void *)(size_t)flow->qos_rule.mask_iova);
3898         rte_free((void *)(size_t)flow->fs_rule.key_iova);
3899         rte_free((void *)(size_t)flow->fs_rule.mask_iova);
3900         /* Now free the flow */
3901         rte_free(flow);
3902
3903 error:
3904         if (ret)
3905                 rte_flow_error_set(error, EPERM,
3906                                    RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3907                                    NULL, "unknown");
3908         return ret;
3909 }
3910
3911 /**
3912  * Destroy user-configured flow rules.
3913  *
3914  * This function skips internal flows rules.
3915  *
3916  * @see rte_flow_flush()
3917  * @see rte_flow_ops
3918  */
3919 static int
3920 dpaa2_flow_flush(struct rte_eth_dev *dev,
3921                 struct rte_flow_error *error)
3922 {
3923         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3924         struct rte_flow *flow = LIST_FIRST(&priv->flows);
3925
3926         while (flow) {
3927                 struct rte_flow *next = LIST_NEXT(flow, next);
3928
3929                 dpaa2_flow_destroy(dev, flow, error);
3930                 flow = next;
3931         }
3932         return 0;
3933 }
3934
3935 static int
3936 dpaa2_flow_query(struct rte_eth_dev *dev __rte_unused,
3937                 struct rte_flow *flow __rte_unused,
3938                 const struct rte_flow_action *actions __rte_unused,
3939                 void *data __rte_unused,
3940                 struct rte_flow_error *error __rte_unused)
3941 {
3942         return 0;
3943 }
3944
3945 /**
3946  * Clean up all flow rules.
3947  *
3948  * Unlike dpaa2_flow_flush(), this function takes care of all remaining flow
3949  * rules regardless of whether they are internal or user-configured.
3950  *
3951  * @param priv
3952  *   Pointer to private structure.
3953  */
3954 void
3955 dpaa2_flow_clean(struct rte_eth_dev *dev)
3956 {
3957         struct rte_flow *flow;
3958         struct dpaa2_dev_priv *priv = dev->data->dev_private;
3959
3960         while ((flow = LIST_FIRST(&priv->flows)))
3961                 dpaa2_flow_destroy(dev, flow, NULL);
3962 }
3963
3964 const struct rte_flow_ops dpaa2_flow_ops = {
3965         .create = dpaa2_flow_create,
3966         .validate = dpaa2_flow_validate,
3967         .destroy = dpaa2_flow_destroy,
3968         .flush  = dpaa2_flow_flush,
3969         .query  = dpaa2_flow_query,
3970 };