xref: /dpdk/drivers/net/mvpp2/mrvl_flow.c (revision c9902a15bd005b6d4fe072cf7b60fe4ee679155f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Marvell International Ltd.
3  * Copyright(c) 2018 Semihalf.
4  * All rights reserved.
5  */
6 
7 #include <rte_flow.h>
8 #include <rte_flow_driver.h>
9 #include <rte_malloc.h>
10 #include <rte_log.h>
11 
12 #include <arpa/inet.h>
13 
14 #include "mrvl_flow.h"
15 #include "mrvl_qos.h"
16 
17 /** Number of rules in the classifier table. */
18 #define MRVL_CLS_MAX_NUM_RULES 20
19 
20 /** Size of the classifier key and mask strings. */
21 #define MRVL_CLS_STR_SIZE_MAX 40
22 
23 #define MRVL_VLAN_ID_MASK 0x0fff
24 #define MRVL_VLAN_PRI_MASK 0x7000
25 #define MRVL_IPV4_DSCP_MASK 0xfc
26 #define MRVL_IPV4_ADDR_MASK 0xffffffff
27 #define MRVL_IPV6_FLOW_MASK 0x0fffff
28 
29 /**
30  * Allocate memory for classifier rule key and mask fields.
31  *
32  * @param field Pointer to the classifier rule.
33  * @returns 0 in case of success, negative value otherwise.
34  */
35 static int
36 mrvl_alloc_key_mask(struct pp2_cls_rule_key_field *field)
37 {
38 	unsigned int id = rte_socket_id();
39 
40 	field->key = rte_zmalloc_socket(NULL, MRVL_CLS_STR_SIZE_MAX, 0, id);
41 	if (!field->key)
42 		goto out;
43 
44 	field->mask = rte_zmalloc_socket(NULL, MRVL_CLS_STR_SIZE_MAX, 0, id);
45 	if (!field->mask)
46 		goto out_mask;
47 
48 	return 0;
49 out_mask:
50 	rte_free(field->key);
51 out:
52 	field->key = NULL;
53 	field->mask = NULL;
54 	return -1;
55 }
56 
57 /**
58  * Free memory allocated for classifier rule key and mask fields.
59  *
60  * @param field Pointer to the classifier rule.
61  */
62 static void
63 mrvl_free_key_mask(struct pp2_cls_rule_key_field *field)
64 {
65 	rte_free(field->key);
66 	rte_free(field->mask);
67 	field->key = NULL;
68 	field->mask = NULL;
69 }
70 
71 /**
72  * Free memory allocated for all classifier rule key and mask fields.
73  *
74  * @param rule Pointer to the classifier table rule.
75  */
76 static void
77 mrvl_free_all_key_mask(struct pp2_cls_tbl_rule *rule)
78 {
79 	int i;
80 
81 	for (i = 0; i < rule->num_fields; i++)
82 		mrvl_free_key_mask(&rule->fields[i]);
83 	rule->num_fields = 0;
84 }
85 
86 /*
87  * Initialize rte flow item parsing.
88  *
89  * @param item Pointer to the flow item.
90  * @param spec_ptr Pointer to the specific item pointer.
91  * @param mask_ptr Pointer to the specific item's mask pointer.
92  * @def_mask Pointer to the default mask.
93  * @size Size of the flow item.
94  * @error Pointer to the rte flow error.
95  * @returns 0 in case of success, negative value otherwise.
96  */
97 static int
98 mrvl_parse_init(const struct rte_flow_item *item,
99 		const void **spec_ptr,
100 		const void **mask_ptr,
101 		const void *def_mask,
102 		unsigned int size,
103 		struct rte_flow_error *error)
104 {
105 	const uint8_t *spec;
106 	const uint8_t *mask;
107 	const uint8_t *last;
108 	uint8_t zeros[size];
109 
110 	memset(zeros, 0, size);
111 
112 	if (item == NULL) {
113 		rte_flow_error_set(error, EINVAL,
114 				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
115 				   "NULL item\n");
116 		return -rte_errno;
117 	}
118 
119 	if ((item->last != NULL || item->mask != NULL) && item->spec == NULL) {
120 		rte_flow_error_set(error, EINVAL,
121 				   RTE_FLOW_ERROR_TYPE_ITEM, item,
122 				   "Mask or last is set without spec\n");
123 		return -rte_errno;
124 	}
125 
126 	/*
127 	 * If "mask" is not set, default mask is used,
128 	 * but if default mask is NULL, "mask" should be set.
129 	 */
130 	if (item->mask == NULL) {
131 		if (def_mask == NULL) {
132 			rte_flow_error_set(error, EINVAL,
133 					   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
134 					   "Mask should be specified\n");
135 			return -rte_errno;
136 		}
137 
138 		mask = (const uint8_t *)def_mask;
139 	} else {
140 		mask = (const uint8_t *)item->mask;
141 	}
142 
143 	spec = (const uint8_t *)item->spec;
144 	last = (const uint8_t *)item->last;
145 
146 	if (spec == NULL) {
147 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
148 				   NULL, "Spec should be specified\n");
149 		return -rte_errno;
150 	}
151 
152 	/*
153 	 * If field values in "last" are either 0 or equal to the corresponding
154 	 * values in "spec" then they are ignored.
155 	 */
156 	if (last != NULL &&
157 	    !memcmp(last, zeros, size) &&
158 	    memcmp(last, spec, size) != 0) {
159 		rte_flow_error_set(error, ENOTSUP,
160 				   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
161 				   "Ranging is not supported\n");
162 		return -rte_errno;
163 	}
164 
165 	*spec_ptr = spec;
166 	*mask_ptr = mask;
167 
168 	return 0;
169 }
170 
171 /**
172  * Parse the eth flow item.
173  *
174  * This will create classifier rule that matches either destination or source
175  * mac.
176  *
177  * @param spec Pointer to the specific flow item.
178  * @param mask Pointer to the specific flow item's mask.
179  * @param parse_dst Parse either destination or source mac address.
180  * @param flow Pointer to the flow.
181  * @return 0 in case of success, negative error value otherwise.
182  */
183 static int
184 mrvl_parse_mac(const struct rte_flow_item_eth *spec,
185 	       const struct rte_flow_item_eth *mask,
186 	       int parse_dst, struct rte_flow *flow)
187 {
188 	struct pp2_cls_rule_key_field *key_field;
189 	const uint8_t *k, *m;
190 
191 	if (parse_dst) {
192 		k = spec->dst.addr_bytes;
193 		m = mask->dst.addr_bytes;
194 
195 		flow->table_key.proto_field[flow->rule.num_fields].field.eth =
196 			MV_NET_ETH_F_DA;
197 	} else {
198 		k = spec->src.addr_bytes;
199 		m = mask->src.addr_bytes;
200 
201 		flow->table_key.proto_field[flow->rule.num_fields].field.eth =
202 			MV_NET_ETH_F_SA;
203 	}
204 
205 	key_field = &flow->rule.fields[flow->rule.num_fields];
206 	mrvl_alloc_key_mask(key_field);
207 	key_field->size = 6;
208 
209 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX,
210 		 RTE_ETHER_ADDR_PRT_FMT,
211 		 k[0], k[1], k[2], k[3], k[4], k[5]);
212 
213 	snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX,
214 		 RTE_ETHER_ADDR_PRT_FMT,
215 		 m[0], m[1], m[2], m[3], m[4], m[5]);
216 
217 	flow->table_key.proto_field[flow->rule.num_fields].proto =
218 		MV_NET_PROTO_ETH;
219 	flow->table_key.key_size += key_field->size;
220 
221 	flow->rule.num_fields += 1;
222 
223 	return 0;
224 }
225 
226 /**
227  * Helper for parsing the eth flow item destination mac address.
228  *
229  * @param spec Pointer to the specific flow item.
230  * @param mask Pointer to the specific flow item's mask.
231  * @param flow Pointer to the flow.
232  * @return 0 in case of success, negative error value otherwise.
233  */
234 static inline int
235 mrvl_parse_dmac(const struct rte_flow_item_eth *spec,
236 		const struct rte_flow_item_eth *mask,
237 		struct rte_flow *flow)
238 {
239 	return mrvl_parse_mac(spec, mask, 1, flow);
240 }
241 
242 /**
243  * Helper for parsing the eth flow item source mac address.
244  *
245  * @param spec Pointer to the specific flow item.
246  * @param mask Pointer to the specific flow item's mask.
247  * @param flow Pointer to the flow.
248  * @return 0 in case of success, negative error value otherwise.
249  */
250 static inline int
251 mrvl_parse_smac(const struct rte_flow_item_eth *spec,
252 		const struct rte_flow_item_eth *mask,
253 		struct rte_flow *flow)
254 {
255 	return mrvl_parse_mac(spec, mask, 0, flow);
256 }
257 
258 /**
259  * Parse the ether type field of the eth flow item.
260  *
261  * @param spec Pointer to the specific flow item.
262  * @param mask Pointer to the specific flow item's mask.
263  * @param flow Pointer to the flow.
264  * @return 0 in case of success, negative error value otherwise.
265  */
266 static int
267 mrvl_parse_type(const struct rte_flow_item_eth *spec,
268 		const struct rte_flow_item_eth *mask __rte_unused,
269 		struct rte_flow *flow)
270 {
271 	struct pp2_cls_rule_key_field *key_field;
272 	uint16_t k;
273 
274 	key_field = &flow->rule.fields[flow->rule.num_fields];
275 	mrvl_alloc_key_mask(key_field);
276 	key_field->size = 2;
277 
278 	k = rte_be_to_cpu_16(spec->type);
279 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
280 
281 	flow->table_key.proto_field[flow->rule.num_fields].proto =
282 		MV_NET_PROTO_ETH;
283 	flow->table_key.proto_field[flow->rule.num_fields].field.eth =
284 		MV_NET_ETH_F_TYPE;
285 	flow->table_key.key_size += key_field->size;
286 
287 	flow->rule.num_fields += 1;
288 
289 	return 0;
290 }
291 
292 /**
293  * Parse the vid field of the vlan rte flow item.
294  *
295  * This will create classifier rule that matches vid.
296  *
297  * @param spec Pointer to the specific flow item.
298  * @param mask Pointer to the specific flow item's mask.
299  * @param flow Pointer to the flow.
300  * @return 0 in case of success, negative error value otherwise.
301  */
302 static int
303 mrvl_parse_vlan_id(const struct rte_flow_item_vlan *spec,
304 		   const struct rte_flow_item_vlan *mask __rte_unused,
305 		   struct rte_flow *flow)
306 {
307 	struct pp2_cls_rule_key_field *key_field;
308 	uint16_t k;
309 
310 	key_field = &flow->rule.fields[flow->rule.num_fields];
311 	mrvl_alloc_key_mask(key_field);
312 	key_field->size = 2;
313 
314 	k = rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_ID_MASK;
315 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
316 
317 	flow->table_key.proto_field[flow->rule.num_fields].proto =
318 		MV_NET_PROTO_VLAN;
319 	flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
320 		MV_NET_VLAN_F_ID;
321 	flow->table_key.key_size += key_field->size;
322 
323 	flow->rule.num_fields += 1;
324 
325 	return 0;
326 }
327 
328 /**
329  * Parse the pri field of the vlan rte flow item.
330  *
331  * This will create classifier rule that matches pri.
332  *
333  * @param spec Pointer to the specific flow item.
334  * @param mask Pointer to the specific flow item's mask.
335  * @param flow Pointer to the flow.
336  * @return 0 in case of success, negative error value otherwise.
337  */
338 static int
339 mrvl_parse_vlan_pri(const struct rte_flow_item_vlan *spec,
340 		    const struct rte_flow_item_vlan *mask __rte_unused,
341 		    struct rte_flow *flow)
342 {
343 	struct pp2_cls_rule_key_field *key_field;
344 	uint16_t k;
345 
346 	key_field = &flow->rule.fields[flow->rule.num_fields];
347 	mrvl_alloc_key_mask(key_field);
348 	key_field->size = 1;
349 
350 	k = (rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_PRI_MASK) >> 13;
351 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
352 
353 	flow->table_key.proto_field[flow->rule.num_fields].proto =
354 		MV_NET_PROTO_VLAN;
355 	flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
356 		MV_NET_VLAN_F_PRI;
357 	flow->table_key.key_size += key_field->size;
358 
359 	flow->rule.num_fields += 1;
360 
361 	return 0;
362 }
363 
364 /**
365  * Parse the dscp field of the ipv4 rte flow item.
366  *
367  * This will create classifier rule that matches dscp field.
368  *
369  * @param spec Pointer to the specific flow item.
370  * @param mask Pointer to the specific flow item's mask.
371  * @param flow Pointer to the flow.
372  * @return 0 in case of success, negative error value otherwise.
373  */
374 static int
375 mrvl_parse_ip4_dscp(const struct rte_flow_item_ipv4 *spec,
376 		    const struct rte_flow_item_ipv4 *mask,
377 		    struct rte_flow *flow)
378 {
379 	struct pp2_cls_rule_key_field *key_field;
380 	uint8_t k, m;
381 
382 	key_field = &flow->rule.fields[flow->rule.num_fields];
383 	mrvl_alloc_key_mask(key_field);
384 	key_field->size = 1;
385 
386 	k = (spec->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) >> 2;
387 	m = (mask->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) >> 2;
388 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
389 	snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);
390 
391 	flow->table_key.proto_field[flow->rule.num_fields].proto =
392 		MV_NET_PROTO_IP4;
393 	flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
394 		MV_NET_IP4_F_DSCP;
395 	flow->table_key.key_size += key_field->size;
396 
397 	flow->rule.num_fields += 1;
398 
399 	return 0;
400 }
401 
402 /**
403  * Parse either source or destination ip addresses of the ipv4 flow item.
404  *
405  * This will create classifier rule that matches either destination
406  * or source ip field.
407  *
408  * @param spec Pointer to the specific flow item.
409  * @param mask Pointer to the specific flow item's mask.
410  * @param parse_dst Parse either destination or source ip address.
411  * @param flow Pointer to the flow.
412  * @return 0 in case of success, negative error value otherwise.
413  */
414 static int
415 mrvl_parse_ip4_addr(const struct rte_flow_item_ipv4 *spec,
416 		    const struct rte_flow_item_ipv4 *mask,
417 		    int parse_dst, struct rte_flow *flow)
418 {
419 	struct pp2_cls_rule_key_field *key_field;
420 	struct in_addr k;
421 	uint32_t m;
422 
423 	memset(&k, 0, sizeof(k));
424 	if (parse_dst) {
425 		k.s_addr = spec->hdr.dst_addr;
426 		m = rte_be_to_cpu_32(mask->hdr.dst_addr);
427 
428 		flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
429 			MV_NET_IP4_F_DA;
430 	} else {
431 		k.s_addr = spec->hdr.src_addr;
432 		m = rte_be_to_cpu_32(mask->hdr.src_addr);
433 
434 		flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
435 			MV_NET_IP4_F_SA;
436 	}
437 
438 	key_field = &flow->rule.fields[flow->rule.num_fields];
439 	mrvl_alloc_key_mask(key_field);
440 	key_field->size = 4;
441 
442 	inet_ntop(AF_INET, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
443 	snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "0x%x", m);
444 
445 	flow->table_key.proto_field[flow->rule.num_fields].proto =
446 		MV_NET_PROTO_IP4;
447 	flow->table_key.key_size += key_field->size;
448 
449 	flow->rule.num_fields += 1;
450 
451 	return 0;
452 }
453 
454 /**
455  * Helper for parsing destination ip of the ipv4 flow item.
456  *
457  * @param spec Pointer to the specific flow item.
458  * @param mask Pointer to the specific flow item's mask.
459  * @param flow Pointer to the flow.
460  * @return 0 in case of success, negative error value otherwise.
461  */
462 static inline int
463 mrvl_parse_ip4_dip(const struct rte_flow_item_ipv4 *spec,
464 		   const struct rte_flow_item_ipv4 *mask,
465 		   struct rte_flow *flow)
466 {
467 	return mrvl_parse_ip4_addr(spec, mask, 1, flow);
468 }
469 
470 /**
471  * Helper for parsing source ip of the ipv4 flow item.
472  *
473  * @param spec Pointer to the specific flow item.
474  * @param mask Pointer to the specific flow item's mask.
475  * @param flow Pointer to the flow.
476  * @return 0 in case of success, negative error value otherwise.
477  */
478 static inline int
479 mrvl_parse_ip4_sip(const struct rte_flow_item_ipv4 *spec,
480 		   const struct rte_flow_item_ipv4 *mask,
481 		   struct rte_flow *flow)
482 {
483 	return mrvl_parse_ip4_addr(spec, mask, 0, flow);
484 }
485 
486 /**
487  * Parse the proto field of the ipv4 rte flow item.
488  *
489  * This will create classifier rule that matches proto field.
490  *
491  * @param spec Pointer to the specific flow item.
492  * @param mask Pointer to the specific flow item's mask.
493  * @param flow Pointer to the flow.
494  * @return 0 in case of success, negative error value otherwise.
495  */
496 static int
497 mrvl_parse_ip4_proto(const struct rte_flow_item_ipv4 *spec,
498 		     const struct rte_flow_item_ipv4 *mask __rte_unused,
499 		     struct rte_flow *flow)
500 {
501 	struct pp2_cls_rule_key_field *key_field;
502 	uint8_t k = spec->hdr.next_proto_id;
503 
504 	key_field = &flow->rule.fields[flow->rule.num_fields];
505 	mrvl_alloc_key_mask(key_field);
506 	key_field->size = 1;
507 
508 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
509 
510 	flow->table_key.proto_field[flow->rule.num_fields].proto =
511 		MV_NET_PROTO_IP4;
512 	flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
513 		MV_NET_IP4_F_PROTO;
514 	flow->table_key.key_size += key_field->size;
515 
516 	flow->rule.num_fields += 1;
517 
518 	return 0;
519 }
520 
521 /**
522  * Parse either source or destination ip addresses of the ipv6 rte flow item.
523  *
524  * This will create classifier rule that matches either destination
525  * or source ip field.
526  *
527  * @param spec Pointer to the specific flow item.
528  * @param mask Pointer to the specific flow item's mask.
529  * @param parse_dst Parse either destination or source ipv6 address.
530  * @param flow Pointer to the flow.
531  * @return 0 in case of success, negative error value otherwise.
532  */
533 static int
534 mrvl_parse_ip6_addr(const struct rte_flow_item_ipv6 *spec,
535 	       const struct rte_flow_item_ipv6 *mask,
536 	       int parse_dst, struct rte_flow *flow)
537 {
538 	struct pp2_cls_rule_key_field *key_field;
539 	int size = sizeof(spec->hdr.dst_addr);
540 	struct in6_addr k, m;
541 
542 	memset(&k, 0, sizeof(k));
543 	if (parse_dst) {
544 		memcpy(k.s6_addr, spec->hdr.dst_addr, size);
545 		memcpy(m.s6_addr, mask->hdr.dst_addr, size);
546 
547 		flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
548 			MV_NET_IP6_F_DA;
549 	} else {
550 		memcpy(k.s6_addr, spec->hdr.src_addr, size);
551 		memcpy(m.s6_addr, mask->hdr.src_addr, size);
552 
553 		flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
554 			MV_NET_IP6_F_SA;
555 	}
556 
557 	key_field = &flow->rule.fields[flow->rule.num_fields];
558 	mrvl_alloc_key_mask(key_field);
559 	key_field->size = 16;
560 
561 	inet_ntop(AF_INET6, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
562 	inet_ntop(AF_INET6, &m, (char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX);
563 
564 	flow->table_key.proto_field[flow->rule.num_fields].proto =
565 		MV_NET_PROTO_IP6;
566 	flow->table_key.key_size += key_field->size;
567 
568 	flow->rule.num_fields += 1;
569 
570 	return 0;
571 }
572 
573 /**
574  * Helper for parsing destination ip of the ipv6 flow item.
575  *
576  * @param spec Pointer to the specific flow item.
577  * @param mask Pointer to the specific flow item's mask.
578  * @param flow Pointer to the flow.
579  * @return 0 in case of success, negative error value otherwise.
580  */
581 static inline int
582 mrvl_parse_ip6_dip(const struct rte_flow_item_ipv6 *spec,
583 		   const struct rte_flow_item_ipv6 *mask,
584 		   struct rte_flow *flow)
585 {
586 	return mrvl_parse_ip6_addr(spec, mask, 1, flow);
587 }
588 
589 /**
590  * Helper for parsing source ip of the ipv6 flow item.
591  *
592  * @param spec Pointer to the specific flow item.
593  * @param mask Pointer to the specific flow item's mask.
594  * @param flow Pointer to the flow.
595  * @return 0 in case of success, negative error value otherwise.
596  */
597 static inline int
598 mrvl_parse_ip6_sip(const struct rte_flow_item_ipv6 *spec,
599 		   const struct rte_flow_item_ipv6 *mask,
600 		   struct rte_flow *flow)
601 {
602 	return mrvl_parse_ip6_addr(spec, mask, 0, flow);
603 }
604 
605 /**
606  * Parse the flow label of the ipv6 flow item.
607  *
608  * This will create classifier rule that matches flow field.
609  *
610  * @param spec Pointer to the specific flow item.
611  * @param mask Pointer to the specific flow item's mask.
612  * @param flow Pointer to the flow.
613  * @return 0 in case of success, negative error value otherwise.
614  */
615 static int
616 mrvl_parse_ip6_flow(const struct rte_flow_item_ipv6 *spec,
617 		    const struct rte_flow_item_ipv6 *mask,
618 		    struct rte_flow *flow)
619 {
620 	struct pp2_cls_rule_key_field *key_field;
621 	uint32_t k = rte_be_to_cpu_32(spec->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK,
622 		 m = rte_be_to_cpu_32(mask->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK;
623 
624 	key_field = &flow->rule.fields[flow->rule.num_fields];
625 	mrvl_alloc_key_mask(key_field);
626 	key_field->size = 3;
627 
628 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
629 	snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);
630 
631 	flow->table_key.proto_field[flow->rule.num_fields].proto =
632 		MV_NET_PROTO_IP6;
633 	flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
634 		MV_NET_IP6_F_FLOW;
635 	flow->table_key.key_size += key_field->size;
636 
637 	flow->rule.num_fields += 1;
638 
639 	return 0;
640 }
641 
642 /**
643  * Parse the next header of the ipv6 flow item.
644  *
645  * This will create classifier rule that matches next header field.
646  *
647  * @param spec Pointer to the specific flow item.
648  * @param mask Pointer to the specific flow item's mask.
649  * @param flow Pointer to the flow.
650  * @return 0 in case of success, negative error value otherwise.
651  */
652 static int
653 mrvl_parse_ip6_next_hdr(const struct rte_flow_item_ipv6 *spec,
654 			const struct rte_flow_item_ipv6 *mask __rte_unused,
655 			struct rte_flow *flow)
656 {
657 	struct pp2_cls_rule_key_field *key_field;
658 	uint8_t k = spec->hdr.proto;
659 
660 	key_field = &flow->rule.fields[flow->rule.num_fields];
661 	mrvl_alloc_key_mask(key_field);
662 	key_field->size = 1;
663 
664 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
665 
666 	flow->table_key.proto_field[flow->rule.num_fields].proto =
667 		MV_NET_PROTO_IP6;
668 	flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
669 		MV_NET_IP6_F_NEXT_HDR;
670 	flow->table_key.key_size += key_field->size;
671 
672 	flow->rule.num_fields += 1;
673 
674 	return 0;
675 }
676 
677 /**
678  * Parse destination or source port of the tcp flow item.
679  *
680  * This will create classifier rule that matches either destination or
681  * source tcp port.
682  *
683  * @param spec Pointer to the specific flow item.
684  * @param mask Pointer to the specific flow item's mask.
685  * @param parse_dst Parse either destination or source port.
686  * @param flow Pointer to the flow.
687  * @return 0 in case of success, negative error value otherwise.
688  */
689 static int
690 mrvl_parse_tcp_port(const struct rte_flow_item_tcp *spec,
691 		    const struct rte_flow_item_tcp *mask __rte_unused,
692 		    int parse_dst, struct rte_flow *flow)
693 {
694 	struct pp2_cls_rule_key_field *key_field;
695 	uint16_t k;
696 
697 	key_field = &flow->rule.fields[flow->rule.num_fields];
698 	mrvl_alloc_key_mask(key_field);
699 	key_field->size = 2;
700 
701 	if (parse_dst) {
702 		k = rte_be_to_cpu_16(spec->hdr.dst_port);
703 
704 		flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
705 			MV_NET_TCP_F_DP;
706 	} else {
707 		k = rte_be_to_cpu_16(spec->hdr.src_port);
708 
709 		flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
710 			MV_NET_TCP_F_SP;
711 	}
712 
713 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
714 
715 	flow->table_key.proto_field[flow->rule.num_fields].proto =
716 		MV_NET_PROTO_TCP;
717 	flow->table_key.key_size += key_field->size;
718 
719 	flow->rule.num_fields += 1;
720 
721 	return 0;
722 }
723 
724 /**
725  * Helper for parsing the tcp source port of the tcp flow item.
726  *
727  * @param spec Pointer to the specific flow item.
728  * @param mask Pointer to the specific flow item's mask.
729  * @param flow Pointer to the flow.
730  * @return 0 in case of success, negative error value otherwise.
731  */
732 static inline int
733 mrvl_parse_tcp_sport(const struct rte_flow_item_tcp *spec,
734 		     const struct rte_flow_item_tcp *mask,
735 		     struct rte_flow *flow)
736 {
737 	return mrvl_parse_tcp_port(spec, mask, 0, flow);
738 }
739 
740 /**
741  * Helper for parsing the tcp destination port of the tcp flow item.
742  *
743  * @param spec Pointer to the specific flow item.
744  * @param mask Pointer to the specific flow item's mask.
745  * @param flow Pointer to the flow.
746  * @return 0 in case of success, negative error value otherwise.
747  */
748 static inline int
749 mrvl_parse_tcp_dport(const struct rte_flow_item_tcp *spec,
750 		     const struct rte_flow_item_tcp *mask,
751 		     struct rte_flow *flow)
752 {
753 	return mrvl_parse_tcp_port(spec, mask, 1, flow);
754 }
755 
756 /**
757  * Parse destination or source port of the udp flow item.
758  *
759  * This will create classifier rule that matches either destination or
760  * source udp port.
761  *
762  * @param spec Pointer to the specific flow item.
763  * @param mask Pointer to the specific flow item's mask.
764  * @param parse_dst Parse either destination or source port.
765  * @param flow Pointer to the flow.
766  * @return 0 in case of success, negative error value otherwise.
767  */
768 static int
769 mrvl_parse_udp_port(const struct rte_flow_item_udp *spec,
770 		    const struct rte_flow_item_udp *mask __rte_unused,
771 		    int parse_dst, struct rte_flow *flow)
772 {
773 	struct pp2_cls_rule_key_field *key_field;
774 	uint16_t k;
775 
776 	key_field = &flow->rule.fields[flow->rule.num_fields];
777 	mrvl_alloc_key_mask(key_field);
778 	key_field->size = 2;
779 
780 	if (parse_dst) {
781 		k = rte_be_to_cpu_16(spec->hdr.dst_port);
782 
783 		flow->table_key.proto_field[flow->rule.num_fields].field.udp =
784 			MV_NET_UDP_F_DP;
785 	} else {
786 		k = rte_be_to_cpu_16(spec->hdr.src_port);
787 
788 		flow->table_key.proto_field[flow->rule.num_fields].field.udp =
789 			MV_NET_UDP_F_SP;
790 	}
791 
792 	snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
793 
794 	flow->table_key.proto_field[flow->rule.num_fields].proto =
795 		MV_NET_PROTO_UDP;
796 	flow->table_key.key_size += key_field->size;
797 
798 	flow->rule.num_fields += 1;
799 
800 	return 0;
801 }
802 
803 /**
804  * Helper for parsing the udp source port of the udp flow item.
805  *
806  * @param spec Pointer to the specific flow item.
807  * @param mask Pointer to the specific flow item's mask.
808  * @param flow Pointer to the flow.
809  * @return 0 in case of success, negative error value otherwise.
810  */
811 static inline int
812 mrvl_parse_udp_sport(const struct rte_flow_item_udp *spec,
813 		     const struct rte_flow_item_udp *mask,
814 		     struct rte_flow *flow)
815 {
816 	return mrvl_parse_udp_port(spec, mask, 0, flow);
817 }
818 
819 /**
820  * Helper for parsing the udp destination port of the udp flow item.
821  *
822  * @param spec Pointer to the specific flow item.
823  * @param mask Pointer to the specific flow item's mask.
824  * @param flow Pointer to the flow.
825  * @return 0 in case of success, negative error value otherwise.
826  */
827 static inline int
828 mrvl_parse_udp_dport(const struct rte_flow_item_udp *spec,
829 		     const struct rte_flow_item_udp *mask,
830 		     struct rte_flow *flow)
831 {
832 	return mrvl_parse_udp_port(spec, mask, 1, flow);
833 }
834 
835 /**
836  * Parse eth flow item.
837  *
838  * @param item Pointer to the flow item.
839  * @param flow Pointer to the flow.
840  * @param error Pointer to the flow error.
841  * @returns 0 on success, negative value otherwise.
842  */
843 static int
844 mrvl_parse_eth(const struct rte_flow_item *item, struct rte_flow *flow,
845 	       struct rte_flow_error *error)
846 {
847 	const struct rte_flow_item_eth *spec = NULL, *mask = NULL;
848 	struct rte_ether_addr zero;
849 	int ret;
850 
851 	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
852 			      &rte_flow_item_eth_mask,
853 			      sizeof(struct rte_flow_item_eth), error);
854 	if (ret)
855 		return ret;
856 
857 	memset(&zero, 0, sizeof(zero));
858 
859 	if (memcmp(&mask->dst, &zero, sizeof(mask->dst))) {
860 		ret = mrvl_parse_dmac(spec, mask, flow);
861 		if (ret)
862 			goto out;
863 	}
864 
865 	if (memcmp(&mask->src, &zero, sizeof(mask->src))) {
866 		ret = mrvl_parse_smac(spec, mask, flow);
867 		if (ret)
868 			goto out;
869 	}
870 
871 	if (mask->type) {
872 		MRVL_LOG(WARNING, "eth type mask is ignored");
873 		ret = mrvl_parse_type(spec, mask, flow);
874 		if (ret)
875 			goto out;
876 	}
877 
878 	return 0;
879 out:
880 	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
881 			   "Reached maximum number of fields in cls tbl key\n");
882 	return -rte_errno;
883 }
884 
885 /**
886  * Parse vlan flow item.
887  *
888  * @param item Pointer to the flow item.
889  * @param flow Pointer to the flow.
890  * @param error Pointer to the flow error.
891  * @returns 0 on success, negative value otherwise.
892  */
893 static int
894 mrvl_parse_vlan(const struct rte_flow_item *item,
895 		struct rte_flow *flow,
896 		struct rte_flow_error *error)
897 {
898 	const struct rte_flow_item_vlan *spec = NULL, *mask = NULL;
899 	uint16_t m;
900 	int ret, i;
901 
902 	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
903 			      &rte_flow_item_vlan_mask,
904 			      sizeof(struct rte_flow_item_vlan), error);
905 	if (ret)
906 		return ret;
907 
908 	m = rte_be_to_cpu_16(mask->tci);
909 	if (m & MRVL_VLAN_ID_MASK) {
910 		MRVL_LOG(WARNING, "vlan id mask is ignored");
911 		ret = mrvl_parse_vlan_id(spec, mask, flow);
912 		if (ret)
913 			goto out;
914 	}
915 
916 	if (m & MRVL_VLAN_PRI_MASK) {
917 		MRVL_LOG(WARNING, "vlan pri mask is ignored");
918 		ret = mrvl_parse_vlan_pri(spec, mask, flow);
919 		if (ret)
920 			goto out;
921 	}
922 
923 	if (mask->inner_type) {
924 		struct rte_flow_item_eth spec_eth = {
925 			.type = spec->inner_type,
926 		};
927 		struct rte_flow_item_eth mask_eth = {
928 			.type = mask->inner_type,
929 		};
930 
931 		/* TPID is not supported so if ETH_TYPE was selected,
932 		 * error is return. else, classify eth-type with the tpid value
933 		 */
934 		for (i = 0; i < flow->rule.num_fields; i++)
935 			if (flow->table_key.proto_field[i].proto ==
936 			    MV_NET_PROTO_ETH &&
937 			    flow->table_key.proto_field[i].field.eth ==
938 			    MV_NET_ETH_F_TYPE) {
939 				rte_flow_error_set(error, ENOTSUP,
940 						   RTE_FLOW_ERROR_TYPE_ITEM,
941 						   item,
942 						   "VLAN TPID matching is not supported");
943 				return -rte_errno;
944 			}
945 
946 		MRVL_LOG(WARNING, "inner eth type mask is ignored");
947 		ret = mrvl_parse_type(&spec_eth, &mask_eth, flow);
948 		if (ret)
949 			goto out;
950 	}
951 
952 	return 0;
953 out:
954 	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
955 			   "Reached maximum number of fields in cls tbl key\n");
956 	return -rte_errno;
957 }
958 
959 /**
960  * Parse ipv4 flow item.
961  *
962  * @param item Pointer to the flow item.
963  * @param flow Pointer to the flow.
964  * @param error Pointer to the flow error.
965  * @returns 0 on success, negative value otherwise.
966  */
967 static int
968 mrvl_parse_ip4(const struct rte_flow_item *item,
969 	       struct rte_flow *flow,
970 	       struct rte_flow_error *error)
971 {
972 	const struct rte_flow_item_ipv4 *spec = NULL, *mask = NULL;
973 	int ret;
974 
975 	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
976 			      &rte_flow_item_ipv4_mask,
977 			      sizeof(struct rte_flow_item_ipv4), error);
978 	if (ret)
979 		return ret;
980 
981 	if (mask->hdr.version_ihl ||
982 	    mask->hdr.total_length ||
983 	    mask->hdr.packet_id ||
984 	    mask->hdr.fragment_offset ||
985 	    mask->hdr.time_to_live ||
986 	    mask->hdr.hdr_checksum) {
987 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
988 				   NULL, "Not supported by classifier\n");
989 		return -rte_errno;
990 	}
991 
992 	if (mask->hdr.type_of_service & MRVL_IPV4_DSCP_MASK) {
993 		ret = mrvl_parse_ip4_dscp(spec, mask, flow);
994 		if (ret)
995 			goto out;
996 	}
997 
998 	if (mask->hdr.src_addr) {
999 		ret = mrvl_parse_ip4_sip(spec, mask, flow);
1000 		if (ret)
1001 			goto out;
1002 	}
1003 
1004 	if (mask->hdr.dst_addr) {
1005 		ret = mrvl_parse_ip4_dip(spec, mask, flow);
1006 		if (ret)
1007 			goto out;
1008 	}
1009 
1010 	if (mask->hdr.next_proto_id) {
1011 		MRVL_LOG(WARNING, "next proto id mask is ignored");
1012 		ret = mrvl_parse_ip4_proto(spec, mask, flow);
1013 		if (ret)
1014 			goto out;
1015 	}
1016 
1017 	return 0;
1018 out:
1019 	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1020 			   "Reached maximum number of fields in cls tbl key\n");
1021 	return -rte_errno;
1022 }
1023 
1024 /**
1025  * Parse ipv6 flow item.
1026  *
1027  * @param item Pointer to the flow item.
1028  * @param flow Pointer to the flow.
1029  * @param error Pointer to the flow error.
1030  * @returns 0 on success, negative value otherwise.
1031  */
1032 static int
1033 mrvl_parse_ip6(const struct rte_flow_item *item,
1034 	       struct rte_flow *flow,
1035 	       struct rte_flow_error *error)
1036 {
1037 	const struct rte_flow_item_ipv6 *spec = NULL, *mask = NULL;
1038 	struct rte_ipv6_hdr zero;
1039 	uint32_t flow_mask;
1040 	int ret;
1041 
1042 	ret = mrvl_parse_init(item, (const void **)&spec,
1043 			      (const void **)&mask,
1044 			      &rte_flow_item_ipv6_mask,
1045 			      sizeof(struct rte_flow_item_ipv6),
1046 			      error);
1047 	if (ret)
1048 		return ret;
1049 
1050 	memset(&zero, 0, sizeof(zero));
1051 
1052 	if (mask->hdr.payload_len ||
1053 	    mask->hdr.hop_limits) {
1054 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1055 				   NULL, "Not supported by classifier\n");
1056 		return -rte_errno;
1057 	}
1058 
1059 	if (memcmp(mask->hdr.src_addr,
1060 		   zero.src_addr, sizeof(mask->hdr.src_addr))) {
1061 		ret = mrvl_parse_ip6_sip(spec, mask, flow);
1062 		if (ret)
1063 			goto out;
1064 	}
1065 
1066 	if (memcmp(mask->hdr.dst_addr,
1067 		   zero.dst_addr, sizeof(mask->hdr.dst_addr))) {
1068 		ret = mrvl_parse_ip6_dip(spec, mask, flow);
1069 		if (ret)
1070 			goto out;
1071 	}
1072 
1073 	flow_mask = rte_be_to_cpu_32(mask->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK;
1074 	if (flow_mask) {
1075 		ret = mrvl_parse_ip6_flow(spec, mask, flow);
1076 		if (ret)
1077 			goto out;
1078 	}
1079 
1080 	if (mask->hdr.proto) {
1081 		MRVL_LOG(WARNING, "next header mask is ignored");
1082 		ret = mrvl_parse_ip6_next_hdr(spec, mask, flow);
1083 		if (ret)
1084 			goto out;
1085 	}
1086 
1087 	return 0;
1088 out:
1089 	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1090 			   "Reached maximum number of fields in cls tbl key\n");
1091 	return -rte_errno;
1092 }
1093 
1094 /**
1095  * Parse tcp flow item.
1096  *
1097  * @param item Pointer to the flow item.
1098  * @param flow Pointer to the flow.
1099  * @param error Pointer to the flow error.
1100  * @returns 0 on success, negative value otherwise.
1101  */
1102 static int
1103 mrvl_parse_tcp(const struct rte_flow_item *item,
1104 	       struct rte_flow *flow,
1105 	       struct rte_flow_error *error)
1106 {
1107 	const struct rte_flow_item_tcp *spec = NULL, *mask = NULL;
1108 	int ret;
1109 
1110 	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
1111 			      &rte_flow_item_tcp_mask,
1112 			      sizeof(struct rte_flow_item_tcp), error);
1113 	if (ret)
1114 		return ret;
1115 
1116 	if (mask->hdr.sent_seq ||
1117 	    mask->hdr.recv_ack ||
1118 	    mask->hdr.data_off ||
1119 	    mask->hdr.tcp_flags ||
1120 	    mask->hdr.rx_win ||
1121 	    mask->hdr.cksum ||
1122 	    mask->hdr.tcp_urp) {
1123 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1124 				   NULL, "Not supported by classifier\n");
1125 		return -rte_errno;
1126 	}
1127 
1128 	if (mask->hdr.src_port) {
1129 		MRVL_LOG(WARNING, "tcp sport mask is ignored");
1130 		ret = mrvl_parse_tcp_sport(spec, mask, flow);
1131 		if (ret)
1132 			goto out;
1133 	}
1134 
1135 	if (mask->hdr.dst_port) {
1136 		MRVL_LOG(WARNING, "tcp dport mask is ignored");
1137 		ret = mrvl_parse_tcp_dport(spec, mask, flow);
1138 		if (ret)
1139 			goto out;
1140 	}
1141 
1142 	return 0;
1143 out:
1144 	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1145 			   "Reached maximum number of fields in cls tbl key\n");
1146 	return -rte_errno;
1147 }
1148 
1149 /**
1150  * Parse udp flow item.
1151  *
1152  * @param item Pointer to the flow item.
1153  * @param flow Pointer to the flow.
1154  * @param error Pointer to the flow error.
1155  * @returns 0 on success, negative value otherwise.
1156  */
1157 static int
1158 mrvl_parse_udp(const struct rte_flow_item *item,
1159 	       struct rte_flow *flow,
1160 	       struct rte_flow_error *error)
1161 {
1162 	const struct rte_flow_item_udp *spec = NULL, *mask = NULL;
1163 	int ret;
1164 
1165 	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
1166 			      &rte_flow_item_udp_mask,
1167 			      sizeof(struct rte_flow_item_udp), error);
1168 	if (ret)
1169 		return ret;
1170 
1171 	if (mask->hdr.dgram_len ||
1172 	    mask->hdr.dgram_cksum) {
1173 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
1174 				   NULL, "Not supported by classifier\n");
1175 		return -rte_errno;
1176 	}
1177 
1178 	if (mask->hdr.src_port) {
1179 		MRVL_LOG(WARNING, "udp sport mask is ignored");
1180 		ret = mrvl_parse_udp_sport(spec, mask, flow);
1181 		if (ret)
1182 			goto out;
1183 	}
1184 
1185 	if (mask->hdr.dst_port) {
1186 		MRVL_LOG(WARNING, "udp dport mask is ignored");
1187 		ret = mrvl_parse_udp_dport(spec, mask, flow);
1188 		if (ret)
1189 			goto out;
1190 	}
1191 
1192 	return 0;
1193 out:
1194 	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1195 			   "Reached maximum number of fields in cls tbl key\n");
1196 	return -rte_errno;
1197 }
1198 
1199 static int
1200 mrvl_string_to_hex_values(const uint8_t *input_string,
1201 			  uint8_t *hex_key,
1202 			  uint8_t *length)
1203 {
1204 	char tmp_arr[3], tmp_string[MRVL_CLS_STR_SIZE_MAX], *string_iter;
1205 	int i;
1206 
1207 	strcpy(tmp_string, (const char *)input_string);
1208 	string_iter = tmp_string;
1209 
1210 	string_iter += 2; /* skip the '0x' */
1211 	*length = ((*length - 2) + 1) / 2;
1212 
1213 	for (i = 0; i < *length; i++) {
1214 		strncpy(tmp_arr, string_iter, 2);
1215 		tmp_arr[2] = '\0';
1216 		if (get_val_securely8(tmp_arr, 16,
1217 				      &hex_key[*length - 1 - i]) < 0)
1218 			return -1;
1219 		string_iter += 2;
1220 	}
1221 
1222 	return 0;
1223 }
1224 
1225 /**
1226  * Parse raw flow item.
1227  *
1228  * @param item Pointer to the flow item.
1229  * @param flow Pointer to the flow.
1230  * @param error Pointer to the flow error.
1231  * @returns 0 on success, negative value otherwise.
1232  */
1233 static int
1234 mrvl_parse_raw(const struct rte_flow_item *item,
1235 	       struct rte_flow *flow,
1236 	       struct rte_flow_error *error)
1237 {
1238 	const struct rte_flow_item_raw *spec = NULL, *mask = NULL;
1239 	struct pp2_cls_rule_key_field *key_field;
1240 	struct mv_net_udf *udf_params;
1241 	uint8_t length;
1242 	int ret;
1243 
1244 	ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
1245 			      &rte_flow_item_raw_mask,
1246 			      sizeof(struct rte_flow_item_raw), error);
1247 	if (ret)
1248 		return ret;
1249 
1250 	if (!spec->pattern) {
1251 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1252 				   NULL, "pattern pointer MUST be given\n");
1253 		return -rte_errno;
1254 	}
1255 
1256 	/* Only hex string is supported; so, it must start with '0x' */
1257 	if (strncmp((const char *)spec->pattern, "0x", 2) != 0)  {
1258 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1259 				   NULL, "'pattern' string must start with '0x'\n");
1260 		return -rte_errno;
1261 	}
1262 
1263 	if (mask->pattern &&
1264 	    strncmp((const char *)mask->pattern, "0x", 2) != 0)  {
1265 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1266 				   NULL, "'mask-pattern' string must start with '0x'\n");
1267 		return -rte_errno;
1268 	}
1269 
1270 	if (mask->search && spec->search) {
1271 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1272 				   NULL, "'search' option must be '0'\n");
1273 		return -rte_errno;
1274 	}
1275 
1276 	if (mask->offset && spec->offset != 0) {
1277 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1278 				   NULL, "'offset' option must be '0'\n");
1279 		return -rte_errno;
1280 	}
1281 
1282 	if (!mask->relative || !spec->relative) {
1283 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1284 				   NULL, "'relative' option must be given and enabled\n");
1285 		return -rte_errno;
1286 	}
1287 
1288 	length = spec->length & mask->length;
1289 	if (!length) {
1290 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1291 				   NULL, "'length' option must be given bigger than '0'\n");
1292 		return -rte_errno;
1293 	}
1294 
1295 	key_field = &flow->rule.fields[flow->rule.num_fields];
1296 	mrvl_alloc_key_mask(key_field);
1297 
1298 	/* pattern and length refer to string bytes. we need to convert it to
1299 	 * values.
1300 	 */
1301 	key_field->size = length;
1302 	ret = mrvl_string_to_hex_values(spec->pattern, key_field->key,
1303 					&key_field->size);
1304 	if (ret) {
1305 		rte_flow_error_set(error, EINVAL,
1306 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1307 				   NULL,
1308 				   "can't convert pattern from string to hex\n");
1309 		return -rte_errno;
1310 	}
1311 	if (mask->pattern) {
1312 		ret = mrvl_string_to_hex_values(mask->pattern, key_field->mask,
1313 						&length);
1314 		if (ret) {
1315 			rte_flow_error_set(error, EINVAL,
1316 					   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
1317 					   NULL,
1318 					   "can't convert mask-pattern from string to hex\n");
1319 			return -rte_errno;
1320 		}
1321 	} else {
1322 		rte_free(key_field->mask);
1323 		key_field->mask = NULL;
1324 	}
1325 
1326 	flow->table_key.proto_field[flow->rule.num_fields].proto =
1327 		MV_NET_UDF;
1328 	udf_params =
1329 		&flow->table_key.proto_field[flow->rule.num_fields].field.udf;
1330 	udf_params->id = flow->next_udf_id++;
1331 	udf_params->size = key_field->size;
1332 	flow->table_key.key_size += key_field->size;
1333 
1334 	flow->rule.num_fields += 1;
1335 
1336 	return 0;
1337 }
1338 
1339 /**
1340  * Structure used to map specific flow pattern to the pattern parse callback
1341  * which will iterate over each pattern item and extract relevant data.
1342  */
1343 static const struct {
1344 	const enum rte_flow_item_type pattern_type;
1345 	int (*parse)(const struct rte_flow_item *pattern,
1346 		struct rte_flow *flow,
1347 		struct rte_flow_error *error);
1348 } mrvl_patterns[] = {
1349 	{ RTE_FLOW_ITEM_TYPE_ETH, mrvl_parse_eth },
1350 	{ RTE_FLOW_ITEM_TYPE_VLAN, mrvl_parse_vlan },
1351 	{ RTE_FLOW_ITEM_TYPE_IPV4, mrvl_parse_ip4 },
1352 	{ RTE_FLOW_ITEM_TYPE_IPV6, mrvl_parse_ip6 },
1353 	{ RTE_FLOW_ITEM_TYPE_TCP, mrvl_parse_tcp },
1354 	{ RTE_FLOW_ITEM_TYPE_UDP, mrvl_parse_udp },
1355 	{ RTE_FLOW_ITEM_TYPE_RAW, mrvl_parse_raw },
1356 	{ RTE_FLOW_ITEM_TYPE_END, NULL }
1357 };
1358 
1359 /**
1360  * Parse flow attribute.
1361  *
1362  * This will check whether the provided attribute's flags are supported.
1363  *
1364  * @param priv Unused
1365  * @param attr Pointer to the flow attribute.
1366  * @param flow Unused
1367  * @param error Pointer to the flow error.
1368  * @returns 0 in case of success, negative value otherwise.
1369  */
1370 static int
1371 mrvl_flow_parse_attr(struct mrvl_priv *priv __rte_unused,
1372 		     const struct rte_flow_attr *attr,
1373 		     struct rte_flow *flow __rte_unused,
1374 		     struct rte_flow_error *error)
1375 {
1376 	if (!attr) {
1377 		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
1378 				   NULL, "NULL attribute");
1379 		return -rte_errno;
1380 	}
1381 
1382 	if (attr->group) {
1383 		rte_flow_error_set(error, ENOTSUP,
1384 				   RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
1385 				   "Groups are not supported");
1386 		return -rte_errno;
1387 	}
1388 	if (attr->priority) {
1389 		rte_flow_error_set(error, ENOTSUP,
1390 				   RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
1391 				   "Priorities are not supported");
1392 		return -rte_errno;
1393 	}
1394 	if (!attr->ingress) {
1395 		rte_flow_error_set(error, ENOTSUP,
1396 				   RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
1397 				   "Only ingress is supported");
1398 		return -rte_errno;
1399 	}
1400 	if (attr->egress) {
1401 		rte_flow_error_set(error, ENOTSUP,
1402 				   RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
1403 				   "Egress is not supported");
1404 		return -rte_errno;
1405 	}
1406 	if (attr->transfer) {
1407 		rte_flow_error_set(error, ENOTSUP,
1408 				   RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
1409 				   "Transfer is not supported");
1410 		return -rte_errno;
1411 	}
1412 
1413 	return 0;
1414 }
1415 
1416 /**
1417  * Parse flow pattern.
1418  *
1419  * Specific classifier rule will be created as well.
1420  *
1421  * @param priv Unused
1422  * @param pattern Pointer to the flow pattern.
1423  * @param flow Pointer to the flow.
1424  * @param error Pointer to the flow error.
1425  * @returns 0 in case of success, negative value otherwise.
1426  */
1427 static int
1428 mrvl_flow_parse_pattern(struct mrvl_priv *priv __rte_unused,
1429 			const struct rte_flow_item pattern[],
1430 			struct rte_flow *flow,
1431 			struct rte_flow_error *error)
1432 {
1433 	unsigned int i, j;
1434 	int ret;
1435 
1436 	for (i = 0; pattern[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {
1437 		if (pattern[i].type == RTE_FLOW_ITEM_TYPE_VOID)
1438 			continue;
1439 		for (j = 0; mrvl_patterns[j].pattern_type !=
1440 			RTE_FLOW_ITEM_TYPE_END; j++) {
1441 			if (mrvl_patterns[j].pattern_type != pattern[i].type)
1442 				continue;
1443 
1444 			if (flow->rule.num_fields >=
1445 			    PP2_CLS_TBL_MAX_NUM_FIELDS) {
1446 				rte_flow_error_set(error, ENOSPC,
1447 						   RTE_FLOW_ERROR_TYPE_ITEM_NUM,
1448 						   NULL,
1449 						   "too many pattern (max %d)");
1450 				return -rte_errno;
1451 			}
1452 
1453 			ret = mrvl_patterns[j].parse(&pattern[i], flow, error);
1454 			if (ret) {
1455 				mrvl_free_all_key_mask(&flow->rule);
1456 				return ret;
1457 			}
1458 			break;
1459 		}
1460 		if (mrvl_patterns[j].pattern_type == RTE_FLOW_ITEM_TYPE_END) {
1461 			rte_flow_error_set(error, ENOTSUP,
1462 					   RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1463 					   "Unsupported pattern");
1464 			return -rte_errno;
1465 		}
1466 	}
1467 
1468 	flow->table_key.num_fields = flow->rule.num_fields;
1469 
1470 	return 0;
1471 }
1472 
1473 /**
1474  * Parse flow actions.
1475  *
1476  * @param priv Pointer to the port's private data.
1477  * @param actions Pointer the action table.
1478  * @param flow Pointer to the flow.
1479  * @param error Pointer to the flow error.
1480  * @returns 0 in case of success, negative value otherwise.
1481  */
1482 static int
1483 mrvl_flow_parse_actions(struct mrvl_priv *priv,
1484 			const struct rte_flow_action actions[],
1485 			struct rte_flow *flow,
1486 			struct rte_flow_error *error)
1487 {
1488 	const struct rte_flow_action *action = actions;
1489 	int specified = 0;
1490 
1491 	for (; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
1492 		if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
1493 			continue;
1494 
1495 		if (action->type == RTE_FLOW_ACTION_TYPE_DROP) {
1496 			flow->cos.ppio = priv->ppio;
1497 			flow->cos.tc = 0;
1498 			flow->action.type = PP2_CLS_TBL_ACT_DROP;
1499 			flow->action.cos = &flow->cos;
1500 			specified++;
1501 		} else if (action->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
1502 			const struct rte_flow_action_queue *q =
1503 				(const struct rte_flow_action_queue *)
1504 				action->conf;
1505 
1506 			if (q->index > priv->nb_rx_queues) {
1507 				rte_flow_error_set(error, EINVAL,
1508 						RTE_FLOW_ERROR_TYPE_ACTION,
1509 						NULL,
1510 						"Queue index out of range");
1511 				return -rte_errno;
1512 			}
1513 
1514 			if (priv->rxq_map[q->index].tc == MRVL_UNKNOWN_TC) {
1515 				/*
1516 				 * Unknown TC mapping, mapping will not have
1517 				 * a correct queue.
1518 				 */
1519 				MRVL_LOG(ERR,
1520 					"Unknown TC mapping for queue %hu eth%hhu",
1521 					q->index, priv->ppio_id);
1522 
1523 				rte_flow_error_set(error, EFAULT,
1524 						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1525 						NULL, NULL);
1526 				return -rte_errno;
1527 			}
1528 
1529 			MRVL_LOG(DEBUG,
1530 				"Action: Assign packets to queue %d, tc:%d, q:%d",
1531 				q->index, priv->rxq_map[q->index].tc,
1532 				priv->rxq_map[q->index].inq);
1533 
1534 			flow->cos.ppio = priv->ppio;
1535 			flow->cos.tc = priv->rxq_map[q->index].tc;
1536 			flow->action.type = PP2_CLS_TBL_ACT_DONE;
1537 			flow->action.cos = &flow->cos;
1538 			specified++;
1539 		} else if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
1540 			const struct rte_flow_action_meter *meter;
1541 			struct mrvl_mtr *mtr;
1542 
1543 			meter = action->conf;
1544 			if (!meter)
1545 				return -rte_flow_error_set(error, EINVAL,
1546 						RTE_FLOW_ERROR_TYPE_ACTION,
1547 						NULL, "Invalid meter\n");
1548 
1549 			LIST_FOREACH(mtr, &priv->mtrs, next)
1550 				if (mtr->mtr_id == meter->mtr_id)
1551 					break;
1552 
1553 			if (!mtr)
1554 				return -rte_flow_error_set(error, EINVAL,
1555 						RTE_FLOW_ERROR_TYPE_ACTION,
1556 						NULL,
1557 						"Meter id does not exist\n");
1558 
1559 			if (!mtr->shared && mtr->refcnt)
1560 				return -rte_flow_error_set(error, EPERM,
1561 						RTE_FLOW_ERROR_TYPE_ACTION,
1562 						NULL,
1563 						"Meter cannot be shared\n");
1564 
1565 			/*
1566 			 * In case cos has already been set
1567 			 * do not modify it.
1568 			 */
1569 			if (!flow->cos.ppio) {
1570 				flow->cos.ppio = priv->ppio;
1571 				flow->cos.tc = 0;
1572 			}
1573 
1574 			flow->action.type = PP2_CLS_TBL_ACT_DONE;
1575 			flow->action.cos = &flow->cos;
1576 			flow->action.plcr = mtr->enabled ? mtr->plcr : NULL;
1577 			flow->mtr = mtr;
1578 			mtr->refcnt++;
1579 			specified++;
1580 		} else {
1581 			rte_flow_error_set(error, ENOTSUP,
1582 					   RTE_FLOW_ERROR_TYPE_ACTION, NULL,
1583 					   "Action not supported");
1584 			return -rte_errno;
1585 		}
1586 	}
1587 
1588 	if (!specified) {
1589 		rte_flow_error_set(error, EINVAL,
1590 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1591 				   "Action not specified");
1592 		return -rte_errno;
1593 	}
1594 
1595 	return 0;
1596 }
1597 
1598 /**
1599  * Parse flow attribute, pattern and actions.
1600  *
1601  * @param priv Pointer to the port's private data.
1602  * @param attr Pointer to the flow attribute.
1603  * @param pattern Pointer to the flow pattern.
1604  * @param actions Pointer to the flow actions.
1605  * @param flow Pointer to the flow.
1606  * @param error Pointer to the flow error.
1607  * @returns 0 on success, negative value otherwise.
1608  */
1609 static int
1610 mrvl_flow_parse(struct mrvl_priv *priv, const struct rte_flow_attr *attr,
1611 		const struct rte_flow_item pattern[],
1612 		const struct rte_flow_action actions[],
1613 		struct rte_flow *flow,
1614 		struct rte_flow_error *error)
1615 {
1616 	int ret;
1617 
1618 	ret = mrvl_flow_parse_attr(priv, attr, flow, error);
1619 	if (ret)
1620 		return ret;
1621 
1622 	ret = mrvl_flow_parse_pattern(priv, pattern, flow, error);
1623 	if (ret)
1624 		return ret;
1625 
1626 	return mrvl_flow_parse_actions(priv, actions, flow, error);
1627 }
1628 
1629 /**
1630  * Get engine type for the given flow.
1631  *
1632  * @param field Pointer to the flow.
1633  * @returns The type of the engine.
1634  */
1635 static inline enum pp2_cls_tbl_type
1636 mrvl_engine_type(const struct rte_flow *flow)
1637 {
1638 	int i, size = 0;
1639 
1640 	for (i = 0; i < flow->rule.num_fields; i++)
1641 		size += flow->rule.fields[i].size;
1642 
1643 	/*
1644 	 * For maskable engine type the key size must be up to 8 bytes.
1645 	 * For keys with size bigger than 8 bytes, engine type must
1646 	 * be set to exact match.
1647 	 */
1648 	if (size > 8)
1649 		return PP2_CLS_TBL_EXACT_MATCH;
1650 
1651 	return PP2_CLS_TBL_MASKABLE;
1652 }
1653 
1654 /**
1655  * Create classifier table.
1656  *
1657  * @param dev Pointer to the device.
1658  * @param flow Pointer to the very first flow.
1659  * @returns 0 in case of success, negative value otherwise.
1660  */
1661 static int
1662 mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
1663 {
1664 	struct mrvl_priv *priv = dev->data->dev_private;
1665 	struct pp2_cls_tbl_key *key = &priv->cls_tbl_params.key;
1666 	int ret;
1667 
1668 	if (priv->cls_tbl) {
1669 		pp2_cls_tbl_deinit(priv->cls_tbl);
1670 		priv->cls_tbl = NULL;
1671 	}
1672 
1673 	memset(&priv->cls_tbl_params, 0, sizeof(priv->cls_tbl_params));
1674 
1675 	priv->cls_tbl_params.type = mrvl_engine_type(first_flow);
1676 	MRVL_LOG(INFO, "Setting cls search engine type to %s",
1677 			priv->cls_tbl_params.type == PP2_CLS_TBL_EXACT_MATCH ?
1678 			"exact" : "maskable");
1679 	priv->cls_tbl_params.max_num_rules = MRVL_CLS_MAX_NUM_RULES;
1680 	priv->cls_tbl_params.default_act.type = PP2_CLS_TBL_ACT_DONE;
1681 	priv->cls_tbl_params.default_act.cos = &first_flow->cos;
1682 	memcpy(key, &first_flow->table_key, sizeof(struct pp2_cls_tbl_key));
1683 
1684 	ret = pp2_cls_tbl_init(&priv->cls_tbl_params, &priv->cls_tbl);
1685 
1686 	return ret;
1687 }
1688 
1689 /**
1690  * Check whether new flow can be added to the table
1691  *
1692  * @param priv Pointer to the port's private data.
1693  * @param flow Pointer to the new flow.
1694  * @return 1 in case flow can be added, 0 otherwise.
1695  */
1696 static inline int
1697 mrvl_flow_can_be_added(struct mrvl_priv *priv, const struct rte_flow *flow)
1698 {
1699 	int same = memcmp(&flow->table_key, &priv->cls_tbl_params.key,
1700 			  sizeof(struct pp2_cls_tbl_key)) == 0;
1701 
1702 	return same && mrvl_engine_type(flow) == priv->cls_tbl_params.type;
1703 }
1704 
1705 /**
1706  * DPDK flow create callback called when flow is to be created.
1707  *
1708  * @param dev Pointer to the device.
1709  * @param attr Pointer to the flow attribute.
1710  * @param pattern Pointer to the flow pattern.
1711  * @param actions Pointer to the flow actions.
1712  * @param error Pointer to the flow error.
1713  * @returns Pointer to the created flow in case of success, NULL otherwise.
1714  */
1715 static struct rte_flow *
1716 mrvl_flow_create(struct rte_eth_dev *dev,
1717 		 const struct rte_flow_attr *attr,
1718 		 const struct rte_flow_item pattern[],
1719 		 const struct rte_flow_action actions[],
1720 		 struct rte_flow_error *error)
1721 {
1722 	struct mrvl_priv *priv = dev->data->dev_private;
1723 	struct rte_flow *flow, *first;
1724 	int ret;
1725 
1726 	if (!dev->data->dev_started) {
1727 		rte_flow_error_set(error, EINVAL,
1728 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1729 				   "Port must be started first\n");
1730 		return NULL;
1731 	}
1732 
1733 	flow = rte_zmalloc_socket(NULL, sizeof(*flow), 0, rte_socket_id());
1734 	if (!flow)
1735 		return NULL;
1736 
1737 	ret = mrvl_flow_parse(priv, attr, pattern, actions, flow, error);
1738 	if (ret)
1739 		goto out;
1740 
1741 	/*
1742 	 * Four cases here:
1743 	 *
1744 	 * 1. In case table does not exist - create one.
1745 	 * 2. In case table exists, is empty and new flow cannot be added
1746 	 *    recreate table.
1747 	 * 3. In case table is not empty and new flow matches table format
1748 	 *    add it.
1749 	 * 4. Otherwise flow cannot be added.
1750 	 */
1751 	first = LIST_FIRST(&priv->flows);
1752 	if (!priv->cls_tbl) {
1753 		ret = mrvl_create_cls_table(dev, flow);
1754 	} else if (!first && !mrvl_flow_can_be_added(priv, flow)) {
1755 		ret = mrvl_create_cls_table(dev, flow);
1756 	} else if (mrvl_flow_can_be_added(priv, flow)) {
1757 		ret = 0;
1758 	} else {
1759 		rte_flow_error_set(error, EINVAL,
1760 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1761 				   "Pattern does not match cls table format\n");
1762 		goto out;
1763 	}
1764 
1765 	if (ret) {
1766 		rte_flow_error_set(error, EINVAL,
1767 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1768 				   "Failed to create cls table\n");
1769 		goto out;
1770 	}
1771 
1772 	ret = pp2_cls_tbl_add_rule(priv->cls_tbl, &flow->rule, &flow->action);
1773 	if (ret) {
1774 		rte_flow_error_set(error, EINVAL,
1775 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1776 				   "Failed to add rule\n");
1777 		goto out;
1778 	}
1779 
1780 	LIST_INSERT_HEAD(&priv->flows, flow, next);
1781 
1782 	return flow;
1783 out:
1784 	rte_free(flow);
1785 	return NULL;
1786 }
1787 
1788 /**
1789  * Remove classifier rule associated with given flow.
1790  *
1791  * @param priv Pointer to the port's private data.
1792  * @param flow Pointer to the flow.
1793  * @param error Pointer to the flow error.
1794  * @returns 0 in case of success, negative value otherwise.
1795  */
1796 static int
1797 mrvl_flow_remove(struct mrvl_priv *priv, struct rte_flow *flow,
1798 		 struct rte_flow_error *error)
1799 {
1800 	int ret;
1801 
1802 	if (!priv->cls_tbl) {
1803 		rte_flow_error_set(error, EINVAL,
1804 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1805 				   "Classifier table not initialized");
1806 		return -rte_errno;
1807 	}
1808 
1809 	ret = pp2_cls_tbl_remove_rule(priv->cls_tbl, &flow->rule);
1810 	if (ret) {
1811 		rte_flow_error_set(error, EINVAL,
1812 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1813 				   "Failed to remove rule");
1814 		return -rte_errno;
1815 	}
1816 
1817 	mrvl_free_all_key_mask(&flow->rule);
1818 
1819 	if (flow->mtr) {
1820 		flow->mtr->refcnt--;
1821 		flow->mtr = NULL;
1822 	}
1823 
1824 	return 0;
1825 }
1826 
1827 /**
1828  * DPDK flow destroy callback called when flow is to be removed.
1829  *
1830  * @param dev Pointer to the device.
1831  * @param flow Pointer to the flow.
1832  * @param error Pointer to the flow error.
1833  * @returns 0 in case of success, negative value otherwise.
1834  */
1835 static int
1836 mrvl_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
1837 		  struct rte_flow_error *error)
1838 {
1839 	struct mrvl_priv *priv = dev->data->dev_private;
1840 	struct rte_flow *f;
1841 	int ret;
1842 
1843 	LIST_FOREACH(f, &priv->flows, next) {
1844 		if (f == flow)
1845 			break;
1846 	}
1847 
1848 	if (!flow) {
1849 		rte_flow_error_set(error, EINVAL,
1850 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1851 				   "Rule was not found");
1852 		return -rte_errno;
1853 	}
1854 
1855 	LIST_REMOVE(f, next);
1856 
1857 	ret = mrvl_flow_remove(priv, flow, error);
1858 	if (ret)
1859 		return ret;
1860 
1861 	rte_free(flow);
1862 
1863 	return 0;
1864 }
1865 
1866 /**
1867  * DPDK flow callback called to verify given attribute, pattern and actions.
1868  *
1869  * @param dev Pointer to the device.
1870  * @param attr Pointer to the flow attribute.
1871  * @param pattern Pointer to the flow pattern.
1872  * @param actions Pointer to the flow actions.
1873  * @param error Pointer to the flow error.
1874  * @returns 0 on success, negative value otherwise.
1875  */
1876 static int
1877 mrvl_flow_validate(struct rte_eth_dev *dev,
1878 		   const struct rte_flow_attr *attr,
1879 		   const struct rte_flow_item pattern[],
1880 		   const struct rte_flow_action actions[],
1881 		   struct rte_flow_error *error)
1882 {
1883 	static struct rte_flow *flow;
1884 
1885 	flow = mrvl_flow_create(dev, attr, pattern, actions, error);
1886 	if (!flow)
1887 		return -rte_errno;
1888 
1889 	mrvl_flow_destroy(dev, flow, error);
1890 
1891 	return 0;
1892 }
1893 
1894 /**
1895  * DPDK flow flush callback called when flows are to be flushed.
1896  *
1897  * @param dev Pointer to the device.
1898  * @param error Pointer to the flow error.
1899  * @returns 0 in case of success, negative value otherwise.
1900  */
1901 static int
1902 mrvl_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
1903 {
1904 	struct mrvl_priv *priv = dev->data->dev_private;
1905 
1906 	while (!LIST_EMPTY(&priv->flows)) {
1907 		struct rte_flow *flow = LIST_FIRST(&priv->flows);
1908 		int ret = mrvl_flow_remove(priv, flow, error);
1909 		if (ret)
1910 			return ret;
1911 
1912 		LIST_REMOVE(flow, next);
1913 		rte_free(flow);
1914 	}
1915 
1916 	if (priv->cls_tbl) {
1917 		pp2_cls_tbl_deinit(priv->cls_tbl);
1918 		priv->cls_tbl = NULL;
1919 	}
1920 
1921 	return 0;
1922 }
1923 
1924 /**
1925  * DPDK flow isolate callback called to isolate port.
1926  *
1927  * @param dev Pointer to the device.
1928  * @param enable Pass 0/1 to disable/enable port isolation.
1929  * @param error Pointer to the flow error.
1930  * @returns 0 in case of success, negative value otherwise.
1931  */
1932 static int
1933 mrvl_flow_isolate(struct rte_eth_dev *dev, int enable,
1934 		  struct rte_flow_error *error)
1935 {
1936 	struct mrvl_priv *priv = dev->data->dev_private;
1937 
1938 	if (dev->data->dev_started) {
1939 		rte_flow_error_set(error, EBUSY,
1940 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1941 				   NULL, "Port must be stopped first\n");
1942 		return -rte_errno;
1943 	}
1944 
1945 	priv->isolated = enable;
1946 
1947 	return 0;
1948 }
1949 
1950 const struct rte_flow_ops mrvl_flow_ops = {
1951 	.validate = mrvl_flow_validate,
1952 	.create = mrvl_flow_create,
1953 	.destroy = mrvl_flow_destroy,
1954 	.flush = mrvl_flow_flush,
1955 	.isolate = mrvl_flow_isolate
1956 };
1957 
1958 /**
1959  * Initialize flow resources.
1960  *
1961  * @param dev Pointer to the device.
1962  */
1963 void
1964 mrvl_flow_init(struct rte_eth_dev *dev)
1965 {
1966 	struct mrvl_priv *priv = dev->data->dev_private;
1967 
1968 	LIST_INIT(&priv->flows);
1969 }
1970 
1971 /**
1972  * Cleanup flow resources.
1973  *
1974  * @param dev Pointer to the device.
1975  */
1976 void
1977 mrvl_flow_deinit(struct rte_eth_dev *dev)
1978 {
1979 	mrvl_flow_flush(dev, NULL);
1980 }
1981