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