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