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