1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7 
8 #include <rte_common.h>
9 #include <rte_byteorder.h>
10 #include <rte_malloc.h>
11 #include <rte_string_fns.h>
12 #include <rte_flow.h>
13 #include <rte_flow_driver.h>
14 #include <rte_tailq.h>
15 
16 #include "rte_eth_softnic_internals.h"
17 #include "rte_eth_softnic.h"
18 
19 #define rte_htons rte_cpu_to_be_16
20 #define rte_htonl rte_cpu_to_be_32
21 
22 #define rte_ntohs rte_be_to_cpu_16
23 #define rte_ntohl rte_be_to_cpu_32
24 
25 static struct rte_flow *
softnic_flow_find(struct softnic_table * table,struct softnic_table_rule_match * rule_match)26 softnic_flow_find(struct softnic_table *table,
27 	struct softnic_table_rule_match *rule_match)
28 {
29 	struct rte_flow *flow;
30 
31 	TAILQ_FOREACH(flow, &table->flows, node)
32 		if (memcmp(&flow->match, rule_match, sizeof(*rule_match)) == 0)
33 			return flow;
34 
35 	return NULL;
36 }
37 
38 int
flow_attr_map_set(struct pmd_internals * softnic,uint32_t group_id,int ingress,const char * pipeline_name,uint32_t table_id)39 flow_attr_map_set(struct pmd_internals *softnic,
40 		uint32_t group_id,
41 		int ingress,
42 		const char *pipeline_name,
43 		uint32_t table_id)
44 {
45 	struct pipeline *pipeline;
46 	struct flow_attr_map *map;
47 
48 	if (group_id >= SOFTNIC_FLOW_MAX_GROUPS ||
49 			pipeline_name == NULL)
50 		return -1;
51 
52 	pipeline = softnic_pipeline_find(softnic, pipeline_name);
53 	if (pipeline == NULL ||
54 			table_id >= pipeline->n_tables)
55 		return -1;
56 
57 	map = (ingress) ? &softnic->flow.ingress_map[group_id] :
58 		&softnic->flow.egress_map[group_id];
59 	strlcpy(map->pipeline_name, pipeline_name, sizeof(map->pipeline_name));
60 	map->table_id = table_id;
61 	map->valid = 1;
62 
63 	return 0;
64 }
65 
66 struct flow_attr_map *
flow_attr_map_get(struct pmd_internals * softnic,uint32_t group_id,int ingress)67 flow_attr_map_get(struct pmd_internals *softnic,
68 		uint32_t group_id,
69 		int ingress)
70 {
71 	if (group_id >= SOFTNIC_FLOW_MAX_GROUPS)
72 		return NULL;
73 
74 	return (ingress) ? &softnic->flow.ingress_map[group_id] :
75 		&softnic->flow.egress_map[group_id];
76 }
77 
78 static int
flow_pipeline_table_get(struct pmd_internals * softnic,const struct rte_flow_attr * attr,const char ** pipeline_name,uint32_t * table_id,struct rte_flow_error * error)79 flow_pipeline_table_get(struct pmd_internals *softnic,
80 		const struct rte_flow_attr *attr,
81 		const char **pipeline_name,
82 		uint32_t *table_id,
83 		struct rte_flow_error *error)
84 {
85 	struct flow_attr_map *map;
86 
87 	if (attr == NULL)
88 		return rte_flow_error_set(error,
89 				EINVAL,
90 				RTE_FLOW_ERROR_TYPE_ATTR,
91 				NULL,
92 				"Null attr");
93 
94 	if (!attr->ingress && !attr->egress)
95 		return rte_flow_error_set(error,
96 				EINVAL,
97 				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
98 				attr,
99 				"Ingress/egress not specified");
100 
101 	if (attr->ingress && attr->egress)
102 		return rte_flow_error_set(error,
103 				EINVAL,
104 				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
105 				attr,
106 				"Setting both ingress and egress is not allowed");
107 
108 	map = flow_attr_map_get(softnic,
109 			attr->group,
110 			attr->ingress);
111 	if (map == NULL ||
112 			map->valid == 0)
113 		return rte_flow_error_set(error,
114 				EINVAL,
115 				RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
116 				attr,
117 				"Invalid group ID");
118 
119 	if (pipeline_name)
120 		*pipeline_name = map->pipeline_name;
121 
122 	if (table_id)
123 		*table_id = map->table_id;
124 
125 	return 0;
126 }
127 
128 union flow_item {
129 	uint8_t raw[TABLE_RULE_MATCH_SIZE_MAX];
130 	struct rte_flow_item_eth eth;
131 	struct rte_flow_item_vlan vlan;
132 	struct rte_flow_item_ipv4 ipv4;
133 	struct rte_flow_item_ipv6 ipv6;
134 	struct rte_flow_item_icmp icmp;
135 	struct rte_flow_item_udp udp;
136 	struct rte_flow_item_tcp tcp;
137 	struct rte_flow_item_sctp sctp;
138 	struct rte_flow_item_vxlan vxlan;
139 	struct rte_flow_item_e_tag e_tag;
140 	struct rte_flow_item_nvgre nvgre;
141 	struct rte_flow_item_mpls mpls;
142 	struct rte_flow_item_gre gre;
143 	struct rte_flow_item_gtp gtp;
144 	struct rte_flow_item_esp esp;
145 	struct rte_flow_item_geneve geneve;
146 	struct rte_flow_item_vxlan_gpe vxlan_gpe;
147 	struct rte_flow_item_arp_eth_ipv4 arp_eth_ipv4;
148 	struct rte_flow_item_ipv6_ext ipv6_ext;
149 	struct rte_flow_item_icmp6 icmp6;
150 	struct rte_flow_item_icmp6_nd_ns icmp6_nd_ns;
151 	struct rte_flow_item_icmp6_nd_na icmp6_nd_na;
152 	struct rte_flow_item_icmp6_nd_opt icmp6_nd_opt;
153 	struct rte_flow_item_icmp6_nd_opt_sla_eth icmp6_nd_opt_sla_eth;
154 	struct rte_flow_item_icmp6_nd_opt_tla_eth icmp6_nd_opt_tla_eth;
155 };
156 
157 static const union flow_item flow_item_raw_mask;
158 
159 static int
flow_item_is_proto(enum rte_flow_item_type type,const void ** mask,size_t * size)160 flow_item_is_proto(enum rte_flow_item_type type,
161 	const void **mask,
162 	size_t *size)
163 {
164 	switch (type) {
165 	case RTE_FLOW_ITEM_TYPE_RAW:
166 		*mask = &flow_item_raw_mask;
167 		*size = sizeof(flow_item_raw_mask);
168 		return 1; /* TRUE */
169 
170 	case RTE_FLOW_ITEM_TYPE_ETH:
171 		*mask = &rte_flow_item_eth_mask;
172 		*size = sizeof(struct rte_ether_hdr);
173 		return 1; /* TRUE */
174 
175 	case RTE_FLOW_ITEM_TYPE_VLAN:
176 		*mask = &rte_flow_item_vlan_mask;
177 		*size = sizeof(struct rte_vlan_hdr);
178 		return 1;
179 
180 	case RTE_FLOW_ITEM_TYPE_IPV4:
181 		*mask = &rte_flow_item_ipv4_mask;
182 		*size = sizeof(struct rte_ipv4_hdr);
183 		return 1;
184 
185 	case RTE_FLOW_ITEM_TYPE_IPV6:
186 		*mask = &rte_flow_item_ipv6_mask;
187 		*size = sizeof(struct rte_ipv6_hdr);
188 		return 1;
189 
190 	case RTE_FLOW_ITEM_TYPE_ICMP:
191 		*mask = &rte_flow_item_icmp_mask;
192 		*size = sizeof(struct rte_flow_item_icmp);
193 		return 1;
194 
195 	case RTE_FLOW_ITEM_TYPE_UDP:
196 		*mask = &rte_flow_item_udp_mask;
197 		*size = sizeof(struct rte_flow_item_udp);
198 		return 1;
199 
200 	case RTE_FLOW_ITEM_TYPE_TCP:
201 		*mask = &rte_flow_item_tcp_mask;
202 		*size = sizeof(struct rte_flow_item_tcp);
203 		return 1;
204 
205 	case RTE_FLOW_ITEM_TYPE_SCTP:
206 		*mask = &rte_flow_item_sctp_mask;
207 		*size = sizeof(struct rte_flow_item_sctp);
208 		return 1;
209 
210 	case RTE_FLOW_ITEM_TYPE_VXLAN:
211 		*mask = &rte_flow_item_vxlan_mask;
212 		*size = sizeof(struct rte_flow_item_vxlan);
213 		return 1;
214 
215 	case RTE_FLOW_ITEM_TYPE_E_TAG:
216 		*mask = &rte_flow_item_e_tag_mask;
217 		*size = sizeof(struct rte_flow_item_e_tag);
218 		return 1;
219 
220 	case RTE_FLOW_ITEM_TYPE_NVGRE:
221 		*mask = &rte_flow_item_nvgre_mask;
222 		*size = sizeof(struct rte_flow_item_nvgre);
223 		return 1;
224 
225 	case RTE_FLOW_ITEM_TYPE_MPLS:
226 		*mask = &rte_flow_item_mpls_mask;
227 		*size = sizeof(struct rte_flow_item_mpls);
228 		return 1;
229 
230 	case RTE_FLOW_ITEM_TYPE_GRE:
231 		*mask = &rte_flow_item_gre_mask;
232 		*size = sizeof(struct rte_flow_item_gre);
233 		return 1;
234 
235 	case RTE_FLOW_ITEM_TYPE_GTP:
236 	case RTE_FLOW_ITEM_TYPE_GTPC:
237 	case RTE_FLOW_ITEM_TYPE_GTPU:
238 		*mask = &rte_flow_item_gtp_mask;
239 		*size = sizeof(struct rte_flow_item_gtp);
240 		return 1;
241 
242 	case RTE_FLOW_ITEM_TYPE_ESP:
243 		*mask = &rte_flow_item_esp_mask;
244 		*size = sizeof(struct rte_flow_item_esp);
245 		return 1;
246 
247 	case RTE_FLOW_ITEM_TYPE_GENEVE:
248 		*mask = &rte_flow_item_geneve_mask;
249 		*size = sizeof(struct rte_flow_item_geneve);
250 		return 1;
251 
252 	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
253 		*mask = &rte_flow_item_vxlan_gpe_mask;
254 		*size = sizeof(struct rte_flow_item_vxlan_gpe);
255 		return 1;
256 
257 	case RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4:
258 		*mask = &rte_flow_item_arp_eth_ipv4_mask;
259 		*size = sizeof(struct rte_flow_item_arp_eth_ipv4);
260 		return 1;
261 
262 	case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
263 		*mask = &rte_flow_item_ipv6_ext_mask;
264 		*size = sizeof(struct rte_flow_item_ipv6_ext);
265 		return 1;
266 
267 	case RTE_FLOW_ITEM_TYPE_ICMP6:
268 		*mask = &rte_flow_item_icmp6_mask;
269 		*size = sizeof(struct rte_flow_item_icmp6);
270 		return 1;
271 
272 	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS:
273 		*mask = &rte_flow_item_icmp6_nd_ns_mask;
274 		*size = sizeof(struct rte_flow_item_icmp6_nd_ns);
275 		return 1;
276 
277 	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA:
278 		*mask = &rte_flow_item_icmp6_nd_na_mask;
279 		*size = sizeof(struct rte_flow_item_icmp6_nd_na);
280 		return 1;
281 
282 	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT:
283 		*mask = &rte_flow_item_icmp6_nd_opt_mask;
284 		*size = sizeof(struct rte_flow_item_icmp6_nd_opt);
285 		return 1;
286 
287 	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH:
288 		*mask = &rte_flow_item_icmp6_nd_opt_sla_eth_mask;
289 		*size = sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth);
290 		return 1;
291 
292 	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH:
293 		*mask = &rte_flow_item_icmp6_nd_opt_tla_eth_mask;
294 		*size = sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth);
295 		return 1;
296 
297 	default: return 0; /* FALSE */
298 	}
299 }
300 
301 static int
flow_item_raw_preprocess(const struct rte_flow_item * item,union flow_item * item_spec,union flow_item * item_mask,size_t * item_size,int * item_disabled,struct rte_flow_error * error)302 flow_item_raw_preprocess(const struct rte_flow_item *item,
303 	union flow_item *item_spec,
304 	union flow_item *item_mask,
305 	size_t *item_size,
306 	int *item_disabled,
307 	struct rte_flow_error *error)
308 {
309 	const struct rte_flow_item_raw *item_raw_spec = item->spec;
310 	const struct rte_flow_item_raw *item_raw_mask = item->mask;
311 	const uint8_t *pattern;
312 	const uint8_t *pattern_mask;
313 	uint8_t *spec = (uint8_t *)item_spec;
314 	uint8_t *mask = (uint8_t *)item_mask;
315 	size_t pattern_length, pattern_offset, i;
316 	int disabled;
317 
318 	if (!item->spec)
319 		return rte_flow_error_set(error,
320 			ENOTSUP,
321 			RTE_FLOW_ERROR_TYPE_ITEM,
322 			item,
323 			"RAW: Null specification");
324 
325 	if (item->last)
326 		return rte_flow_error_set(error,
327 			ENOTSUP,
328 			RTE_FLOW_ERROR_TYPE_ITEM,
329 			item,
330 			"RAW: Range not allowed (last must be NULL)");
331 
332 	if (item_raw_spec->relative == 0)
333 		return rte_flow_error_set(error,
334 			ENOTSUP,
335 			RTE_FLOW_ERROR_TYPE_ITEM,
336 			item,
337 			"RAW: Absolute offset not supported");
338 
339 	if (item_raw_spec->search)
340 		return rte_flow_error_set(error,
341 			ENOTSUP,
342 			RTE_FLOW_ERROR_TYPE_ITEM,
343 			item,
344 			"RAW: Search not supported");
345 
346 	if (item_raw_spec->offset < 0)
347 		return rte_flow_error_set(error,
348 			ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
349 			item,
350 			"RAW: Negative offset not supported");
351 
352 	if (item_raw_spec->length == 0)
353 		return rte_flow_error_set(error,
354 			ENOTSUP,
355 			RTE_FLOW_ERROR_TYPE_ITEM,
356 			item,
357 			"RAW: Zero pattern length");
358 
359 	if (item_raw_spec->offset + item_raw_spec->length >
360 		TABLE_RULE_MATCH_SIZE_MAX)
361 		return rte_flow_error_set(error,
362 			ENOTSUP,
363 			RTE_FLOW_ERROR_TYPE_ITEM,
364 			item,
365 			"RAW: Item too big");
366 
367 	if (!item_raw_spec->pattern && item_raw_mask && item_raw_mask->pattern)
368 		return rte_flow_error_set(error,
369 			ENOTSUP,
370 			RTE_FLOW_ERROR_TYPE_ITEM,
371 			item,
372 			"RAW: Non-NULL pattern mask not allowed with NULL pattern");
373 
374 	pattern = item_raw_spec->pattern;
375 	pattern_mask = (item_raw_mask) ? item_raw_mask->pattern : NULL;
376 	pattern_length = (size_t)item_raw_spec->length;
377 	pattern_offset = (size_t)item_raw_spec->offset;
378 
379 	disabled = 0;
380 	if (pattern_mask == NULL)
381 		disabled = 1;
382 	else
383 		for (i = 0; i < pattern_length; i++)
384 			if ((pattern)[i])
385 				disabled = 1;
386 
387 	memset(spec, 0, TABLE_RULE_MATCH_SIZE_MAX);
388 	if (pattern)
389 		memcpy(&spec[pattern_offset], pattern, pattern_length);
390 
391 	memset(mask, 0, TABLE_RULE_MATCH_SIZE_MAX);
392 	if (pattern_mask)
393 		memcpy(&mask[pattern_offset], pattern_mask, pattern_length);
394 
395 	*item_size = pattern_offset + pattern_length;
396 	*item_disabled = disabled;
397 
398 	return 0;
399 }
400 
401 static int
flow_item_proto_preprocess(const struct rte_flow_item * item,union flow_item * item_spec,union flow_item * item_mask,size_t * item_size,int * item_disabled,struct rte_flow_error * error)402 flow_item_proto_preprocess(const struct rte_flow_item *item,
403 	union flow_item *item_spec,
404 	union flow_item *item_mask,
405 	size_t *item_size,
406 	int *item_disabled,
407 	struct rte_flow_error *error)
408 {
409 	const void *mask_default;
410 	uint8_t *spec = (uint8_t *)item_spec;
411 	uint8_t *mask = (uint8_t *)item_mask;
412 	size_t size, i;
413 
414 	if (!flow_item_is_proto(item->type, &mask_default, &size))
415 		return rte_flow_error_set(error,
416 			ENOTSUP,
417 			RTE_FLOW_ERROR_TYPE_ITEM,
418 			item,
419 			"Item type not supported");
420 
421 	if (item->type == RTE_FLOW_ITEM_TYPE_RAW)
422 		return flow_item_raw_preprocess(item,
423 			item_spec,
424 			item_mask,
425 			item_size,
426 			item_disabled,
427 			error);
428 
429 	/* spec */
430 	if (!item->spec) {
431 		/* If spec is NULL, then last and mask also have to be NULL. */
432 		if (item->last || item->mask)
433 			return rte_flow_error_set(error,
434 				EINVAL,
435 				RTE_FLOW_ERROR_TYPE_ITEM,
436 				item,
437 				"Invalid item (NULL spec with non-NULL last or mask)");
438 
439 		memset(item_spec, 0, size);
440 		memset(item_mask, 0, size);
441 		*item_size = size;
442 		*item_disabled = 1; /* TRUE */
443 		return 0;
444 	}
445 
446 	memcpy(spec, item->spec, size);
447 	*item_size = size;
448 
449 	/* mask */
450 	if (item->mask)
451 		memcpy(mask, item->mask, size);
452 	else
453 		memcpy(mask, mask_default, size);
454 
455 	/* disabled */
456 	for (i = 0; i < size; i++)
457 		if (mask[i])
458 			break;
459 	*item_disabled = (i == size) ? 1 : 0;
460 
461 	/* Apply mask over spec. */
462 	for (i = 0; i < size; i++)
463 		spec[i] &= mask[i];
464 
465 	/* last */
466 	if (item->last) {
467 		uint8_t last[size];
468 
469 		/* init last */
470 		memcpy(last, item->last, size);
471 		for (i = 0; i < size; i++)
472 			last[i] &= mask[i];
473 
474 		/* check for range */
475 		for (i = 0; i < size; i++)
476 			if (last[i] != spec[i])
477 				return rte_flow_error_set(error,
478 					ENOTSUP,
479 					RTE_FLOW_ERROR_TYPE_ITEM,
480 					item,
481 					"Range not supported");
482 	}
483 
484 	return 0;
485 }
486 
487 /***
488  * Skip disabled protocol items and VOID items
489  * until any of the mutually exclusive conditions
490  * from the list below takes place:
491  *    (A) A protocol present in the proto_mask
492  *        is met (either ENABLED or DISABLED);
493  *    (B) A protocol NOT present in the proto_mask is met in ENABLED state;
494  *    (C) The END item is met.
495  */
496 static int
flow_item_skip_disabled_protos(const struct rte_flow_item ** item,uint64_t proto_mask,size_t * length,struct rte_flow_error * error)497 flow_item_skip_disabled_protos(const struct rte_flow_item **item,
498 	uint64_t proto_mask,
499 	size_t *length,
500 	struct rte_flow_error *error)
501 {
502 	size_t len = 0;
503 
504 	for ( ; (*item)->type != RTE_FLOW_ITEM_TYPE_END; (*item)++) {
505 		union flow_item spec, mask;
506 		size_t size;
507 		int disabled = 0, status;
508 
509 		if ((*item)->type == RTE_FLOW_ITEM_TYPE_VOID)
510 			continue;
511 
512 		status = flow_item_proto_preprocess(*item,
513 				&spec,
514 				&mask,
515 				&size,
516 				&disabled,
517 				error);
518 		if (status)
519 			return status;
520 
521 		if ((proto_mask & (1LLU << (*item)->type)) ||
522 				!disabled)
523 			break;
524 
525 		len += size;
526 	}
527 
528 	if (length)
529 		*length = len;
530 
531 	return 0;
532 }
533 
534 #define FLOW_ITEM_PROTO_IP \
535 	((1LLU << RTE_FLOW_ITEM_TYPE_IPV4) | \
536 	 (1LLU << RTE_FLOW_ITEM_TYPE_IPV6))
537 
538 static void
flow_item_skip_void(const struct rte_flow_item ** item)539 flow_item_skip_void(const struct rte_flow_item **item)
540 {
541 	for ( ; ; (*item)++)
542 		if ((*item)->type != RTE_FLOW_ITEM_TYPE_VOID)
543 			return;
544 }
545 
546 #define IP_PROTOCOL_TCP 0x06
547 #define IP_PROTOCOL_UDP 0x11
548 #define IP_PROTOCOL_SCTP 0x84
549 
550 static int
mask_to_depth(uint64_t mask,uint32_t * depth)551 mask_to_depth(uint64_t mask,
552 		uint32_t *depth)
553 {
554 	uint64_t n;
555 
556 	if (mask == UINT64_MAX) {
557 		if (depth)
558 			*depth = 64;
559 
560 		return 0;
561 	}
562 
563 	mask = ~mask;
564 
565 	if (mask & (mask + 1))
566 		return -1;
567 
568 	n = __builtin_popcountll(mask);
569 	if (depth)
570 		*depth = (uint32_t)(64 - n);
571 
572 	return 0;
573 }
574 
575 static int
ipv4_mask_to_depth(uint32_t mask,uint32_t * depth)576 ipv4_mask_to_depth(uint32_t mask,
577 		uint32_t *depth)
578 {
579 	uint32_t d;
580 	int status;
581 
582 	status = mask_to_depth(mask | (UINT64_MAX << 32), &d);
583 	if (status)
584 		return status;
585 
586 	d -= 32;
587 	if (depth)
588 		*depth = d;
589 
590 	return 0;
591 }
592 
593 static int
ipv6_mask_to_depth(uint8_t * mask,uint32_t * depth)594 ipv6_mask_to_depth(uint8_t *mask,
595 	uint32_t *depth)
596 {
597 	uint64_t *m = (uint64_t *)mask;
598 	uint64_t m0 = rte_be_to_cpu_64(m[0]);
599 	uint64_t m1 = rte_be_to_cpu_64(m[1]);
600 	uint32_t d0, d1;
601 	int status;
602 
603 	status = mask_to_depth(m0, &d0);
604 	if (status)
605 		return status;
606 
607 	status = mask_to_depth(m1, &d1);
608 	if (status)
609 		return status;
610 
611 	if (d0 < 64 && d1)
612 		return -1;
613 
614 	if (depth)
615 		*depth = d0 + d1;
616 
617 	return 0;
618 }
619 
620 static int
port_mask_to_range(uint16_t port,uint16_t port_mask,uint16_t * port0,uint16_t * port1)621 port_mask_to_range(uint16_t port,
622 	uint16_t port_mask,
623 	uint16_t *port0,
624 	uint16_t *port1)
625 {
626 	int status;
627 	uint16_t p0, p1;
628 
629 	status = mask_to_depth(port_mask | (UINT64_MAX << 16), NULL);
630 	if (status)
631 		return -1;
632 
633 	p0 = port & port_mask;
634 	p1 = p0 | ~port_mask;
635 
636 	if (port0)
637 		*port0 = p0;
638 
639 	if (port1)
640 		*port1 = p1;
641 
642 	return 0;
643 }
644 
645 static int
flow_rule_match_acl_get(struct pmd_internals * softnic __rte_unused,struct pipeline * pipeline __rte_unused,struct softnic_table * table __rte_unused,const struct rte_flow_attr * attr,const struct rte_flow_item * item,struct softnic_table_rule_match * rule_match,struct rte_flow_error * error)646 flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
647 		struct pipeline *pipeline __rte_unused,
648 		struct softnic_table *table __rte_unused,
649 		const struct rte_flow_attr *attr,
650 		const struct rte_flow_item *item,
651 		struct softnic_table_rule_match *rule_match,
652 		struct rte_flow_error *error)
653 {
654 	union flow_item spec, mask;
655 	size_t size, length = 0;
656 	int disabled = 0, status;
657 	uint8_t ip_proto, ip_proto_mask;
658 
659 	memset(rule_match, 0, sizeof(*rule_match));
660 	rule_match->match_type = TABLE_ACL;
661 	rule_match->match.acl.priority = attr->priority;
662 
663 	/* VOID or disabled protos only, if any. */
664 	status = flow_item_skip_disabled_protos(&item,
665 			FLOW_ITEM_PROTO_IP, &length, error);
666 	if (status)
667 		return status;
668 
669 	/* IP only. */
670 	status = flow_item_proto_preprocess(item, &spec, &mask,
671 			&size, &disabled, error);
672 	if (status)
673 		return status;
674 
675 	switch (item->type) {
676 	case RTE_FLOW_ITEM_TYPE_IPV4:
677 	{
678 		uint32_t sa_depth, da_depth;
679 
680 		status = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.src_addr),
681 				&sa_depth);
682 		if (status)
683 			return rte_flow_error_set(error,
684 				EINVAL,
685 				RTE_FLOW_ERROR_TYPE_ITEM,
686 				item,
687 				"ACL: Illegal IPv4 header source address mask");
688 
689 		status = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.dst_addr),
690 				&da_depth);
691 		if (status)
692 			return rte_flow_error_set(error,
693 				EINVAL,
694 				RTE_FLOW_ERROR_TYPE_ITEM,
695 				item,
696 				"ACL: Illegal IPv4 header destination address mask");
697 
698 		ip_proto = spec.ipv4.hdr.next_proto_id;
699 		ip_proto_mask = mask.ipv4.hdr.next_proto_id;
700 
701 		rule_match->match.acl.ip_version = 1;
702 		rule_match->match.acl.ipv4.sa =
703 			rte_ntohl(spec.ipv4.hdr.src_addr);
704 		rule_match->match.acl.ipv4.da =
705 			rte_ntohl(spec.ipv4.hdr.dst_addr);
706 		rule_match->match.acl.sa_depth = sa_depth;
707 		rule_match->match.acl.da_depth = da_depth;
708 		rule_match->match.acl.proto = ip_proto;
709 		rule_match->match.acl.proto_mask = ip_proto_mask;
710 		break;
711 	} /* RTE_FLOW_ITEM_TYPE_IPV4 */
712 
713 	case RTE_FLOW_ITEM_TYPE_IPV6:
714 	{
715 		uint32_t sa_depth, da_depth;
716 
717 		status = ipv6_mask_to_depth(mask.ipv6.hdr.src_addr, &sa_depth);
718 		if (status)
719 			return rte_flow_error_set(error,
720 				EINVAL,
721 				RTE_FLOW_ERROR_TYPE_ITEM,
722 				item,
723 				"ACL: Illegal IPv6 header source address mask");
724 
725 		status = ipv6_mask_to_depth(mask.ipv6.hdr.dst_addr, &da_depth);
726 		if (status)
727 			return rte_flow_error_set(error,
728 				EINVAL,
729 				RTE_FLOW_ERROR_TYPE_ITEM,
730 				item,
731 				"ACL: Illegal IPv6 header destination address mask");
732 
733 		ip_proto = spec.ipv6.hdr.proto;
734 		ip_proto_mask = mask.ipv6.hdr.proto;
735 
736 		rule_match->match.acl.ip_version = 0;
737 		memcpy(rule_match->match.acl.ipv6.sa,
738 			spec.ipv6.hdr.src_addr,
739 			sizeof(spec.ipv6.hdr.src_addr));
740 		memcpy(rule_match->match.acl.ipv6.da,
741 			spec.ipv6.hdr.dst_addr,
742 			sizeof(spec.ipv6.hdr.dst_addr));
743 		rule_match->match.acl.sa_depth = sa_depth;
744 		rule_match->match.acl.da_depth = da_depth;
745 		rule_match->match.acl.proto = ip_proto;
746 		rule_match->match.acl.proto_mask = ip_proto_mask;
747 		break;
748 	} /* RTE_FLOW_ITEM_TYPE_IPV6 */
749 
750 	default:
751 		return rte_flow_error_set(error,
752 			ENOTSUP,
753 			RTE_FLOW_ERROR_TYPE_ITEM,
754 			item,
755 			"ACL: IP protocol required");
756 	} /* switch */
757 
758 	if (ip_proto_mask != UINT8_MAX)
759 		return rte_flow_error_set(error,
760 			EINVAL,
761 			RTE_FLOW_ERROR_TYPE_ITEM,
762 			item,
763 			"ACL: Illegal IP protocol mask");
764 
765 	item++;
766 
767 	/* VOID only, if any. */
768 	flow_item_skip_void(&item);
769 
770 	/* TCP/UDP/SCTP only. */
771 	status = flow_item_proto_preprocess(item, &spec, &mask,
772 			&size, &disabled, error);
773 	if (status)
774 		return status;
775 
776 	switch (item->type) {
777 	case RTE_FLOW_ITEM_TYPE_TCP:
778 	{
779 		uint16_t sp0, sp1, dp0, dp1;
780 
781 		if (ip_proto != IP_PROTOCOL_TCP)
782 			return rte_flow_error_set(error,
783 				EINVAL,
784 				RTE_FLOW_ERROR_TYPE_ITEM,
785 				item,
786 				"ACL: Item type is TCP, but IP protocol is not");
787 
788 		status = port_mask_to_range(rte_ntohs(spec.tcp.hdr.src_port),
789 				rte_ntohs(mask.tcp.hdr.src_port),
790 				&sp0,
791 				&sp1);
792 
793 		if (status)
794 			return rte_flow_error_set(error,
795 				EINVAL,
796 				RTE_FLOW_ERROR_TYPE_ITEM,
797 				item,
798 				"ACL: Illegal TCP source port mask");
799 
800 		status = port_mask_to_range(rte_ntohs(spec.tcp.hdr.dst_port),
801 				rte_ntohs(mask.tcp.hdr.dst_port),
802 				&dp0,
803 				&dp1);
804 
805 		if (status)
806 			return rte_flow_error_set(error,
807 				EINVAL,
808 				RTE_FLOW_ERROR_TYPE_ITEM,
809 				item,
810 				"ACL: Illegal TCP destination port mask");
811 
812 		rule_match->match.acl.sp0 = sp0;
813 		rule_match->match.acl.sp1 = sp1;
814 		rule_match->match.acl.dp0 = dp0;
815 		rule_match->match.acl.dp1 = dp1;
816 
817 		break;
818 	} /* RTE_FLOW_ITEM_TYPE_TCP */
819 
820 	case RTE_FLOW_ITEM_TYPE_UDP:
821 	{
822 		uint16_t sp0, sp1, dp0, dp1;
823 
824 		if (ip_proto != IP_PROTOCOL_UDP)
825 			return rte_flow_error_set(error,
826 				EINVAL,
827 				RTE_FLOW_ERROR_TYPE_ITEM,
828 				item,
829 				"ACL: Item type is UDP, but IP protocol is not");
830 
831 		status = port_mask_to_range(rte_ntohs(spec.udp.hdr.src_port),
832 			rte_ntohs(mask.udp.hdr.src_port),
833 			&sp0,
834 			&sp1);
835 		if (status)
836 			return rte_flow_error_set(error,
837 				EINVAL,
838 				RTE_FLOW_ERROR_TYPE_ITEM,
839 				item,
840 				"ACL: Illegal UDP source port mask");
841 
842 		status = port_mask_to_range(rte_ntohs(spec.udp.hdr.dst_port),
843 			rte_ntohs(mask.udp.hdr.dst_port),
844 			&dp0,
845 			&dp1);
846 		if (status)
847 			return rte_flow_error_set(error,
848 				EINVAL,
849 				RTE_FLOW_ERROR_TYPE_ITEM,
850 				item,
851 				"ACL: Illegal UDP destination port mask");
852 
853 		rule_match->match.acl.sp0 = sp0;
854 		rule_match->match.acl.sp1 = sp1;
855 		rule_match->match.acl.dp0 = dp0;
856 		rule_match->match.acl.dp1 = dp1;
857 
858 		break;
859 	} /* RTE_FLOW_ITEM_TYPE_UDP */
860 
861 	case RTE_FLOW_ITEM_TYPE_SCTP:
862 	{
863 		uint16_t sp0, sp1, dp0, dp1;
864 
865 		if (ip_proto != IP_PROTOCOL_SCTP)
866 			return rte_flow_error_set(error,
867 				EINVAL,
868 				RTE_FLOW_ERROR_TYPE_ITEM,
869 				item,
870 				"ACL: Item type is SCTP, but IP protocol is not");
871 
872 		status = port_mask_to_range(rte_ntohs(spec.sctp.hdr.src_port),
873 			rte_ntohs(mask.sctp.hdr.src_port),
874 			&sp0,
875 			&sp1);
876 
877 		if (status)
878 			return rte_flow_error_set(error,
879 				EINVAL,
880 				RTE_FLOW_ERROR_TYPE_ITEM,
881 				item,
882 				"ACL: Illegal SCTP source port mask");
883 
884 		status = port_mask_to_range(rte_ntohs(spec.sctp.hdr.dst_port),
885 			rte_ntohs(mask.sctp.hdr.dst_port),
886 			&dp0,
887 			&dp1);
888 		if (status)
889 			return rte_flow_error_set(error,
890 				EINVAL,
891 				RTE_FLOW_ERROR_TYPE_ITEM,
892 				item,
893 				"ACL: Illegal SCTP destination port mask");
894 
895 		rule_match->match.acl.sp0 = sp0;
896 		rule_match->match.acl.sp1 = sp1;
897 		rule_match->match.acl.dp0 = dp0;
898 		rule_match->match.acl.dp1 = dp1;
899 
900 		break;
901 	} /* RTE_FLOW_ITEM_TYPE_SCTP */
902 
903 	default:
904 		return rte_flow_error_set(error,
905 			ENOTSUP,
906 			RTE_FLOW_ERROR_TYPE_ITEM,
907 			item,
908 			"ACL: TCP/UDP/SCTP required");
909 	} /* switch */
910 
911 	item++;
912 
913 	/* VOID or disabled protos only, if any. */
914 	status = flow_item_skip_disabled_protos(&item, 0, NULL, error);
915 	if (status)
916 		return status;
917 
918 	/* END only. */
919 	if (item->type != RTE_FLOW_ITEM_TYPE_END)
920 		return rte_flow_error_set(error,
921 			EINVAL,
922 			RTE_FLOW_ERROR_TYPE_ITEM,
923 			item,
924 			"ACL: Expecting END item");
925 
926 	return 0;
927 }
928 
929 /***
930  * Both *tmask* and *fmask* are byte arrays of size *tsize* and *fsize*
931  * respectively.
932  * They are located within a larger buffer at offsets *toffset* and *foffset*
933  * respectivelly. Both *tmask* and *fmask* represent bitmasks for the larger
934  * buffer.
935  * Question: are the two masks equivalent?
936  *
937  * Notes:
938  * 1. Offset basically indicates that the first offset bytes in the buffer
939  *    are "don't care", so offset is equivalent to pre-pending an "all-zeros"
940  *    array of *offset* bytes to the *mask*.
941  * 2. Each *mask* might contain a number of zero bytes at the beginning or
942  *    at the end.
943  * 3. Bytes in the larger buffer after the end of the *mask* are also considered
944  *    "don't care", so they are equivalent to appending an "all-zeros" array of
945  *    bytes to the *mask*.
946  *
947  * Example:
948  * Buffer = [xx xx xx xx xx xx xx xx], buffer size = 8 bytes
949  * tmask = [00 22 00 33 00], toffset = 2, tsize = 5
950  *    => buffer mask = [00 00 00 22 00 33 00 00]
951  * fmask = [22 00 33], foffset = 3, fsize = 3 =>
952  *    => buffer mask = [00 00 00 22 00 33 00 00]
953  * Therefore, the tmask and fmask from this example are equivalent.
954  */
955 static int
hash_key_mask_is_same(uint8_t * tmask,size_t toffset,size_t tsize,uint8_t * fmask,size_t foffset,size_t fsize,size_t * toffset_plus,size_t * foffset_plus)956 hash_key_mask_is_same(uint8_t *tmask,
957 	size_t toffset,
958 	size_t tsize,
959 	uint8_t *fmask,
960 	size_t foffset,
961 	size_t fsize,
962 	size_t *toffset_plus,
963 	size_t *foffset_plus)
964 {
965 	size_t tpos; /* Position of first non-zero byte in the tmask buffer. */
966 	size_t fpos; /* Position of first non-zero byte in the fmask buffer. */
967 
968 	/* Compute tpos and fpos. */
969 	for (tpos = 0; tmask[tpos] == 0; tpos++)
970 		;
971 	for (fpos = 0; fmask[fpos] == 0; fpos++)
972 		;
973 
974 	if (toffset + tpos != foffset + fpos)
975 		return 0; /* FALSE */
976 
977 	tsize -= tpos;
978 	fsize -= fpos;
979 
980 	if (tsize < fsize) {
981 		size_t i;
982 
983 		for (i = 0; i < tsize; i++)
984 			if (tmask[tpos + i] != fmask[fpos + i])
985 				return 0; /* FALSE */
986 
987 		for ( ; i < fsize; i++)
988 			if (fmask[fpos + i])
989 				return 0; /* FALSE */
990 	} else {
991 		size_t i;
992 
993 		for (i = 0; i < fsize; i++)
994 			if (tmask[tpos + i] != fmask[fpos + i])
995 				return 0; /* FALSE */
996 
997 		for ( ; i < tsize; i++)
998 			if (tmask[tpos + i])
999 				return 0; /* FALSE */
1000 	}
1001 
1002 	if (toffset_plus)
1003 		*toffset_plus = tpos;
1004 
1005 	if (foffset_plus)
1006 		*foffset_plus = fpos;
1007 
1008 	return 1; /* TRUE */
1009 }
1010 
1011 static int
flow_rule_match_hash_get(struct pmd_internals * softnic __rte_unused,struct pipeline * pipeline __rte_unused,struct softnic_table * table,const struct rte_flow_attr * attr __rte_unused,const struct rte_flow_item * item,struct softnic_table_rule_match * rule_match,struct rte_flow_error * error)1012 flow_rule_match_hash_get(struct pmd_internals *softnic __rte_unused,
1013 	struct pipeline *pipeline __rte_unused,
1014 	struct softnic_table *table,
1015 	const struct rte_flow_attr *attr __rte_unused,
1016 	const struct rte_flow_item *item,
1017 	struct softnic_table_rule_match *rule_match,
1018 	struct rte_flow_error *error)
1019 {
1020 	struct softnic_table_rule_match_hash key, key_mask;
1021 	struct softnic_table_hash_params *params = &table->params.match.hash;
1022 	size_t offset = 0, length = 0, tpos, fpos;
1023 	int status;
1024 
1025 	memset(&key, 0, sizeof(key));
1026 	memset(&key_mask, 0, sizeof(key_mask));
1027 
1028 	/* VOID or disabled protos only, if any. */
1029 	status = flow_item_skip_disabled_protos(&item, 0, &offset, error);
1030 	if (status)
1031 		return status;
1032 
1033 	if (item->type == RTE_FLOW_ITEM_TYPE_END)
1034 		return rte_flow_error_set(error,
1035 			EINVAL,
1036 			RTE_FLOW_ERROR_TYPE_ITEM,
1037 			item,
1038 			"HASH: END detected too early");
1039 
1040 	/* VOID or any protocols (enabled or disabled). */
1041 	for ( ; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
1042 		union flow_item spec, mask;
1043 		size_t size;
1044 		int disabled, status;
1045 
1046 		if (item->type == RTE_FLOW_ITEM_TYPE_VOID)
1047 			continue;
1048 
1049 		status = flow_item_proto_preprocess(item,
1050 			&spec,
1051 			&mask,
1052 			&size,
1053 			&disabled,
1054 			error);
1055 		if (status)
1056 			return status;
1057 
1058 		if (length + size > sizeof(key)) {
1059 			if (disabled)
1060 				break;
1061 
1062 			return rte_flow_error_set(error,
1063 				ENOTSUP,
1064 				RTE_FLOW_ERROR_TYPE_ITEM,
1065 				item,
1066 				"HASH: Item too big");
1067 		}
1068 
1069 		memcpy(&key.key[length], &spec, size);
1070 		memcpy(&key_mask.key[length], &mask, size);
1071 		length += size;
1072 	}
1073 
1074 	if (item->type != RTE_FLOW_ITEM_TYPE_END) {
1075 		/* VOID or disabled protos only, if any. */
1076 		status = flow_item_skip_disabled_protos(&item, 0, NULL, error);
1077 		if (status)
1078 			return status;
1079 
1080 		/* END only. */
1081 		if (item->type != RTE_FLOW_ITEM_TYPE_END)
1082 			return rte_flow_error_set(error,
1083 				EINVAL,
1084 				RTE_FLOW_ERROR_TYPE_ITEM,
1085 				item,
1086 				"HASH: Expecting END item");
1087 	}
1088 
1089 	/* Compare flow key mask against table key mask. */
1090 	offset += sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
1091 
1092 	if (!hash_key_mask_is_same(params->key_mask,
1093 		params->key_offset,
1094 		params->key_size,
1095 		key_mask.key,
1096 		offset,
1097 		length,
1098 		&tpos,
1099 		&fpos))
1100 		return rte_flow_error_set(error,
1101 			EINVAL,
1102 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1103 			NULL,
1104 			"HASH: Item list is not observing the match format");
1105 
1106 	/* Rule match. */
1107 	memset(rule_match, 0, sizeof(*rule_match));
1108 	rule_match->match_type = TABLE_HASH;
1109 	memcpy(&rule_match->match.hash.key[tpos],
1110 		&key.key[fpos],
1111 		RTE_MIN(sizeof(rule_match->match.hash.key) - tpos,
1112 			length - fpos));
1113 
1114 	return 0;
1115 }
1116 
1117 static int
flow_rule_match_get(struct pmd_internals * softnic,struct pipeline * pipeline,struct softnic_table * table,const struct rte_flow_attr * attr,const struct rte_flow_item * item,struct softnic_table_rule_match * rule_match,struct rte_flow_error * error)1118 flow_rule_match_get(struct pmd_internals *softnic,
1119 		struct pipeline *pipeline,
1120 		struct softnic_table *table,
1121 		const struct rte_flow_attr *attr,
1122 		const struct rte_flow_item *item,
1123 		struct softnic_table_rule_match *rule_match,
1124 		struct rte_flow_error *error)
1125 {
1126 	switch (table->params.match_type) {
1127 	case TABLE_ACL:
1128 		return flow_rule_match_acl_get(softnic,
1129 			pipeline,
1130 			table,
1131 			attr,
1132 			item,
1133 			rule_match,
1134 			error);
1135 
1136 		/* FALLTHROUGH */
1137 
1138 	case TABLE_HASH:
1139 		return flow_rule_match_hash_get(softnic,
1140 			pipeline,
1141 			table,
1142 			attr,
1143 			item,
1144 			rule_match,
1145 			error);
1146 
1147 		/* FALLTHROUGH */
1148 
1149 	default:
1150 		return rte_flow_error_set(error,
1151 			ENOTSUP,
1152 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1153 			NULL,
1154 			"Unsupported pipeline table match type");
1155 	}
1156 }
1157 
1158 static int
flow_rule_action_get(struct pmd_internals * softnic,struct pipeline * pipeline,struct softnic_table * table,const struct rte_flow_attr * attr,const struct rte_flow_action * action,struct softnic_table_rule_action * rule_action,struct rte_flow_error * error)1159 flow_rule_action_get(struct pmd_internals *softnic,
1160 	struct pipeline *pipeline,
1161 	struct softnic_table *table,
1162 	const struct rte_flow_attr *attr,
1163 	const struct rte_flow_action *action,
1164 	struct softnic_table_rule_action *rule_action,
1165 	struct rte_flow_error *error)
1166 {
1167 	struct softnic_table_action_profile *profile;
1168 	struct softnic_table_action_profile_params *params;
1169 	int n_jump_queue_rss_drop = 0;
1170 	int n_count = 0;
1171 	int n_mark = 0;
1172 	int n_vxlan_decap = 0;
1173 
1174 	profile = softnic_table_action_profile_find(softnic,
1175 		table->params.action_profile_name);
1176 	if (profile == NULL)
1177 		return rte_flow_error_set(error,
1178 			EINVAL,
1179 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1180 			action,
1181 			"JUMP: Table action profile");
1182 
1183 	params = &profile->params;
1184 
1185 	for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
1186 		if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
1187 			continue;
1188 
1189 		switch (action->type) {
1190 		case RTE_FLOW_ACTION_TYPE_JUMP:
1191 		{
1192 			const struct rte_flow_action_jump *conf = action->conf;
1193 			struct flow_attr_map *map;
1194 
1195 			if (conf == NULL)
1196 				return rte_flow_error_set(error,
1197 					EINVAL,
1198 					RTE_FLOW_ERROR_TYPE_ACTION,
1199 					action,
1200 					"JUMP: Null configuration");
1201 
1202 			if (n_jump_queue_rss_drop)
1203 				return rte_flow_error_set(error,
1204 					EINVAL,
1205 					RTE_FLOW_ERROR_TYPE_ACTION,
1206 					action,
1207 					"Only one termination action is"
1208 					" allowed per flow");
1209 
1210 			if ((params->action_mask &
1211 				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
1212 				return rte_flow_error_set(error,
1213 					EINVAL,
1214 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1215 					NULL,
1216 					"JUMP action not enabled for this table");
1217 
1218 			n_jump_queue_rss_drop = 1;
1219 
1220 			map = flow_attr_map_get(softnic,
1221 				conf->group,
1222 				attr->ingress);
1223 			if (map == NULL || map->valid == 0)
1224 				return rte_flow_error_set(error,
1225 					EINVAL,
1226 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1227 					NULL,
1228 					"JUMP: Invalid group mapping");
1229 
1230 			if (strcmp(pipeline->name, map->pipeline_name) != 0)
1231 				return rte_flow_error_set(error,
1232 					ENOTSUP,
1233 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1234 					NULL,
1235 					"JUMP: Jump to table in different pipeline");
1236 
1237 			/* RTE_TABLE_ACTION_FWD */
1238 			rule_action->fwd.action = RTE_PIPELINE_ACTION_TABLE;
1239 			rule_action->fwd.id = map->table_id;
1240 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
1241 			break;
1242 		} /* RTE_FLOW_ACTION_TYPE_JUMP */
1243 
1244 		case RTE_FLOW_ACTION_TYPE_QUEUE:
1245 		{
1246 			char name[NAME_SIZE];
1247 			struct rte_eth_dev *dev;
1248 			const struct rte_flow_action_queue *conf = action->conf;
1249 			uint32_t port_id;
1250 			int status;
1251 
1252 			if (conf == NULL)
1253 				return rte_flow_error_set(error,
1254 					EINVAL,
1255 					RTE_FLOW_ERROR_TYPE_ACTION,
1256 					action,
1257 					"QUEUE: Null configuration");
1258 
1259 			if (n_jump_queue_rss_drop)
1260 				return rte_flow_error_set(error,
1261 					EINVAL,
1262 					RTE_FLOW_ERROR_TYPE_ACTION,
1263 					action,
1264 					"Only one termination action is allowed"
1265 					" per flow");
1266 
1267 			if ((params->action_mask &
1268 				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
1269 				return rte_flow_error_set(error,
1270 					EINVAL,
1271 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1272 					NULL,
1273 					"QUEUE action not enabled for this table");
1274 
1275 			n_jump_queue_rss_drop = 1;
1276 
1277 			dev = ETHDEV(softnic);
1278 			if (dev == NULL ||
1279 				conf->index >= dev->data->nb_rx_queues)
1280 				return rte_flow_error_set(error,
1281 					EINVAL,
1282 					RTE_FLOW_ERROR_TYPE_ACTION,
1283 					action,
1284 					"QUEUE: Invalid RX queue ID");
1285 
1286 			snprintf(name, sizeof(name), "RXQ%u",
1287 					(uint32_t)conf->index);
1288 
1289 			status = softnic_pipeline_port_out_find(softnic,
1290 				pipeline->name,
1291 				name,
1292 				&port_id);
1293 			if (status)
1294 				return rte_flow_error_set(error,
1295 					ENOTSUP,
1296 					RTE_FLOW_ERROR_TYPE_ACTION,
1297 					action,
1298 					"QUEUE: RX queue not accessible from this pipeline");
1299 
1300 			/* RTE_TABLE_ACTION_FWD */
1301 			rule_action->fwd.action = RTE_PIPELINE_ACTION_PORT;
1302 			rule_action->fwd.id = port_id;
1303 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
1304 			break;
1305 		} /*RTE_FLOW_ACTION_TYPE_QUEUE */
1306 
1307 		case RTE_FLOW_ACTION_TYPE_RSS:
1308 		{
1309 			const struct rte_flow_action_rss *conf = action->conf;
1310 			uint32_t i;
1311 
1312 			if (conf == NULL)
1313 				return rte_flow_error_set(error,
1314 					EINVAL,
1315 					RTE_FLOW_ERROR_TYPE_ACTION,
1316 					action,
1317 					"RSS: Null configuration");
1318 
1319 			if (!rte_is_power_of_2(conf->queue_num))
1320 				return rte_flow_error_set(error,
1321 					EINVAL,
1322 					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1323 					conf,
1324 					"RSS: Number of queues must be a power of 2");
1325 
1326 			if (conf->queue_num > RTE_DIM(rule_action->lb.out))
1327 				return rte_flow_error_set(error,
1328 					EINVAL,
1329 					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1330 					conf,
1331 					"RSS: Number of queues too big");
1332 
1333 			if (n_jump_queue_rss_drop)
1334 				return rte_flow_error_set(error,
1335 					EINVAL,
1336 					RTE_FLOW_ERROR_TYPE_ACTION,
1337 					action,
1338 					"Only one termination action is allowed per flow");
1339 
1340 			if (((params->action_mask &
1341 				(1LLU << RTE_TABLE_ACTION_FWD)) == 0) ||
1342 				((params->action_mask &
1343 				(1LLU << RTE_TABLE_ACTION_LB)) == 0))
1344 				return rte_flow_error_set(error,
1345 					ENOTSUP,
1346 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1347 					NULL,
1348 					"RSS action not supported by this table");
1349 
1350 			if (params->lb.out_offset !=
1351 				pipeline->params.offset_port_id)
1352 				return rte_flow_error_set(error,
1353 					EINVAL,
1354 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1355 					NULL,
1356 					"RSS action not supported by this pipeline");
1357 
1358 			n_jump_queue_rss_drop = 1;
1359 
1360 			/* RTE_TABLE_ACTION_LB */
1361 			for (i = 0; i < conf->queue_num; i++) {
1362 				char name[NAME_SIZE];
1363 				struct rte_eth_dev *dev;
1364 				uint32_t port_id;
1365 				int status;
1366 
1367 				dev = ETHDEV(softnic);
1368 				if (dev == NULL ||
1369 					conf->queue[i] >=
1370 						dev->data->nb_rx_queues)
1371 					return rte_flow_error_set(error,
1372 						EINVAL,
1373 						RTE_FLOW_ERROR_TYPE_ACTION,
1374 						action,
1375 						"RSS: Invalid RX queue ID");
1376 
1377 				snprintf(name, sizeof(name), "RXQ%u",
1378 					(uint32_t)conf->queue[i]);
1379 
1380 				status = softnic_pipeline_port_out_find(softnic,
1381 					pipeline->name,
1382 					name,
1383 					&port_id);
1384 				if (status)
1385 					return rte_flow_error_set(error,
1386 						ENOTSUP,
1387 						RTE_FLOW_ERROR_TYPE_ACTION,
1388 						action,
1389 						"RSS: RX queue not accessible from this pipeline");
1390 
1391 				rule_action->lb.out[i] = port_id;
1392 			}
1393 
1394 			for ( ; i < RTE_DIM(rule_action->lb.out); i++)
1395 				rule_action->lb.out[i] =
1396 				rule_action->lb.out[i % conf->queue_num];
1397 
1398 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_LB;
1399 
1400 			/* RTE_TABLE_ACTION_FWD */
1401 			rule_action->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
1402 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
1403 			break;
1404 		} /* RTE_FLOW_ACTION_TYPE_RSS */
1405 
1406 		case RTE_FLOW_ACTION_TYPE_DROP:
1407 		{
1408 			const void *conf = action->conf;
1409 
1410 			if (conf != NULL)
1411 				return rte_flow_error_set(error,
1412 					EINVAL,
1413 					RTE_FLOW_ERROR_TYPE_ACTION,
1414 					action,
1415 					"DROP: No configuration required");
1416 
1417 			if (n_jump_queue_rss_drop)
1418 				return rte_flow_error_set(error,
1419 					EINVAL,
1420 					RTE_FLOW_ERROR_TYPE_ACTION,
1421 					action,
1422 					"Only one termination action is allowed per flow");
1423 			if ((params->action_mask &
1424 				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
1425 				return rte_flow_error_set(error,
1426 					ENOTSUP,
1427 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1428 					NULL,
1429 					"DROP action not supported by this table");
1430 
1431 			n_jump_queue_rss_drop = 1;
1432 
1433 			/* RTE_TABLE_ACTION_FWD */
1434 			rule_action->fwd.action = RTE_PIPELINE_ACTION_DROP;
1435 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
1436 			break;
1437 		} /* RTE_FLOW_ACTION_TYPE_DROP */
1438 
1439 		case RTE_FLOW_ACTION_TYPE_COUNT:
1440 		{
1441 			const struct rte_flow_action_count *conf = action->conf;
1442 
1443 			if (conf == NULL)
1444 				return rte_flow_error_set(error,
1445 					EINVAL,
1446 					RTE_FLOW_ERROR_TYPE_ACTION,
1447 					action,
1448 					"COUNT: Null configuration");
1449 
1450 			if (conf->shared)
1451 				return rte_flow_error_set(error,
1452 					ENOTSUP,
1453 					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1454 					conf,
1455 					"COUNT: Shared counters not supported");
1456 
1457 			if (n_count)
1458 				return rte_flow_error_set(error,
1459 					ENOTSUP,
1460 					RTE_FLOW_ERROR_TYPE_ACTION,
1461 					action,
1462 					"Only one COUNT action per flow");
1463 
1464 			if ((params->action_mask &
1465 				(1LLU << RTE_TABLE_ACTION_STATS)) == 0)
1466 				return rte_flow_error_set(error,
1467 					ENOTSUP,
1468 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1469 					NULL,
1470 					"COUNT action not supported by this table");
1471 
1472 			n_count = 1;
1473 
1474 			/* RTE_TABLE_ACTION_STATS */
1475 			rule_action->stats.n_packets = 0;
1476 			rule_action->stats.n_bytes = 0;
1477 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
1478 			break;
1479 		} /* RTE_FLOW_ACTION_TYPE_COUNT */
1480 
1481 		case RTE_FLOW_ACTION_TYPE_MARK:
1482 		{
1483 			const struct rte_flow_action_mark *conf = action->conf;
1484 
1485 			if (conf == NULL)
1486 				return rte_flow_error_set(error,
1487 					EINVAL,
1488 					RTE_FLOW_ERROR_TYPE_ACTION,
1489 					action,
1490 					"MARK: Null configuration");
1491 
1492 			if (n_mark)
1493 				return rte_flow_error_set(error,
1494 					ENOTSUP,
1495 					RTE_FLOW_ERROR_TYPE_ACTION,
1496 					action,
1497 					"Only one MARK action per flow");
1498 
1499 			if ((params->action_mask &
1500 				(1LLU << RTE_TABLE_ACTION_TAG)) == 0)
1501 				return rte_flow_error_set(error,
1502 					ENOTSUP,
1503 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1504 					NULL,
1505 					"MARK action not supported by this table");
1506 
1507 			n_mark = 1;
1508 
1509 			/* RTE_TABLE_ACTION_TAG */
1510 			rule_action->tag.tag = conf->id;
1511 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_TAG;
1512 			break;
1513 		} /* RTE_FLOW_ACTION_TYPE_MARK */
1514 
1515 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
1516 		{
1517 			const struct rte_flow_action_mark *conf = action->conf;
1518 
1519 			if (conf)
1520 				return rte_flow_error_set(error,
1521 					EINVAL,
1522 					RTE_FLOW_ERROR_TYPE_ACTION,
1523 					action,
1524 					"VXLAN DECAP: Non-null configuration");
1525 
1526 			if (n_vxlan_decap)
1527 				return rte_flow_error_set(error,
1528 					ENOTSUP,
1529 					RTE_FLOW_ERROR_TYPE_ACTION,
1530 					action,
1531 					"Only one VXLAN DECAP action per flow");
1532 
1533 			if ((params->action_mask &
1534 				(1LLU << RTE_TABLE_ACTION_DECAP)) == 0)
1535 				return rte_flow_error_set(error,
1536 					ENOTSUP,
1537 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1538 					NULL,
1539 					"VXLAN DECAP action not supported by this table");
1540 
1541 			n_vxlan_decap = 1;
1542 
1543 			/* RTE_TABLE_ACTION_DECAP */
1544 			rule_action->decap.n = 50; /* Ether/IPv4/UDP/VXLAN */
1545 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;
1546 			break;
1547 		} /* RTE_FLOW_ACTION_TYPE_VXLAN_DECAP */
1548 
1549 		case RTE_FLOW_ACTION_TYPE_METER:
1550 		{
1551 			const struct rte_flow_action_meter *conf = action->conf;
1552 			struct softnic_mtr_meter_profile *mp;
1553 			struct softnic_mtr *m;
1554 			uint32_t table_id = table - pipeline->table;
1555 			uint32_t meter_profile_id;
1556 			int status;
1557 
1558 			if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0)
1559 				return rte_flow_error_set(error,
1560 					EINVAL,
1561 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1562 					NULL,
1563 					"METER: Table action not supported");
1564 
1565 			if (params->mtr.n_tc != 1)
1566 				return rte_flow_error_set(error,
1567 					EINVAL,
1568 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1569 					NULL,
1570 					"METER: Multiple TCs not supported");
1571 
1572 			if (conf == NULL)
1573 				return rte_flow_error_set(error,
1574 					EINVAL,
1575 					RTE_FLOW_ERROR_TYPE_ACTION,
1576 					action,
1577 					"METER: Null configuration");
1578 
1579 			m = softnic_mtr_find(softnic, conf->mtr_id);
1580 
1581 			if (m == NULL)
1582 				return rte_flow_error_set(error,
1583 					EINVAL,
1584 					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1585 					NULL,
1586 					"METER: Invalid meter ID");
1587 
1588 			if (m->flow)
1589 				return rte_flow_error_set(error,
1590 					EINVAL,
1591 					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
1592 					NULL,
1593 					"METER: Meter already attached to a flow");
1594 
1595 			meter_profile_id = m->params.meter_profile_id;
1596 			mp = softnic_mtr_meter_profile_find(softnic, meter_profile_id);
1597 
1598 			/* Add meter profile to pipeline table */
1599 			if (!softnic_pipeline_table_meter_profile_find(table,
1600 					meter_profile_id)) {
1601 				struct rte_table_action_meter_profile profile;
1602 
1603 				memset(&profile, 0, sizeof(profile));
1604 				profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
1605 				profile.trtcm.cir = mp->params.trtcm_rfc2698.cir;
1606 				profile.trtcm.pir = mp->params.trtcm_rfc2698.pir;
1607 				profile.trtcm.cbs = mp->params.trtcm_rfc2698.cbs;
1608 				profile.trtcm.pbs = mp->params.trtcm_rfc2698.pbs;
1609 
1610 				status = softnic_pipeline_table_mtr_profile_add(softnic,
1611 						pipeline->name,
1612 						table_id,
1613 						meter_profile_id,
1614 						&profile);
1615 				if (status) {
1616 					rte_flow_error_set(error,
1617 						EINVAL,
1618 						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1619 						NULL,
1620 						"METER: Table meter profile add failed");
1621 					return -1;
1622 				}
1623 			}
1624 
1625 			/* RTE_TABLE_ACTION_METER */
1626 			rule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;
1627 			rule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =
1628 				softnic_table_action_policer(m->params.action[RTE_COLOR_GREEN]);
1629 			rule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =
1630 				softnic_table_action_policer(m->params.action[RTE_COLOR_YELLOW]);
1631 			rule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =
1632 				softnic_table_action_policer(m->params.action[RTE_COLOR_RED]);
1633 			rule_action->mtr.tc_mask = 1;
1634 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
1635 			break;
1636 		} /* RTE_FLOW_ACTION_TYPE_METER */
1637 
1638 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
1639 		{
1640 			const struct rte_flow_action_vxlan_encap *conf =
1641 				action->conf;
1642 			const struct rte_flow_item *item;
1643 			union flow_item spec, mask;
1644 			int disabled = 0, status;
1645 			size_t size;
1646 
1647 			if (conf == NULL)
1648 				return rte_flow_error_set(error,
1649 					EINVAL,
1650 					RTE_FLOW_ERROR_TYPE_ACTION,
1651 					action,
1652 					"VXLAN ENCAP: Null configuration");
1653 
1654 			item = conf->definition;
1655 			if (item == NULL)
1656 				return rte_flow_error_set(error,
1657 					EINVAL,
1658 					RTE_FLOW_ERROR_TYPE_ACTION,
1659 					action,
1660 					"VXLAN ENCAP: Null configuration definition");
1661 
1662 			if (!(params->action_mask &
1663 					(1LLU << RTE_TABLE_ACTION_ENCAP)))
1664 				return rte_flow_error_set(error,
1665 					EINVAL,
1666 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1667 					NULL,
1668 					"VXLAN ENCAP: Encap action not enabled for this table");
1669 
1670 			/* Check for Ether. */
1671 			flow_item_skip_void(&item);
1672 			status = flow_item_proto_preprocess(item, &spec, &mask,
1673 				&size, &disabled, error);
1674 			if (status)
1675 				return status;
1676 
1677 			if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
1678 				return rte_flow_error_set(error,
1679 					EINVAL,
1680 					RTE_FLOW_ERROR_TYPE_ITEM,
1681 					item,
1682 					"VXLAN ENCAP: first encap item should be ether");
1683 			}
1684 			rte_ether_addr_copy(&spec.eth.dst,
1685 					&rule_action->encap.vxlan.ether.da);
1686 			rte_ether_addr_copy(&spec.eth.src,
1687 					&rule_action->encap.vxlan.ether.sa);
1688 
1689 			item++;
1690 
1691 			/* Check for VLAN. */
1692 			flow_item_skip_void(&item);
1693 			status = flow_item_proto_preprocess(item, &spec, &mask,
1694 					&size, &disabled, error);
1695 			if (status)
1696 				return status;
1697 
1698 			if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
1699 				if (!params->encap.vxlan.vlan)
1700 					return rte_flow_error_set(error,
1701 						ENOTSUP,
1702 						RTE_FLOW_ERROR_TYPE_ITEM,
1703 						item,
1704 						"VXLAN ENCAP: vlan encap not supported by table");
1705 
1706 				uint16_t tci = rte_ntohs(spec.vlan.tci);
1707 				rule_action->encap.vxlan.vlan.pcp =
1708 					tci >> 13;
1709 				rule_action->encap.vxlan.vlan.dei =
1710 					(tci >> 12) & 0x1;
1711 				rule_action->encap.vxlan.vlan.vid =
1712 					tci & 0xfff;
1713 
1714 				item++;
1715 
1716 				flow_item_skip_void(&item);
1717 				status = flow_item_proto_preprocess(item, &spec,
1718 						&mask, &size, &disabled, error);
1719 				if (status)
1720 					return status;
1721 			} else {
1722 				if (params->encap.vxlan.vlan)
1723 					return rte_flow_error_set(error,
1724 						ENOTSUP,
1725 						RTE_FLOW_ERROR_TYPE_ITEM,
1726 						item,
1727 						"VXLAN ENCAP: expecting vlan encap item");
1728 			}
1729 
1730 			/* Check for IPV4/IPV6. */
1731 			switch (item->type) {
1732 			case RTE_FLOW_ITEM_TYPE_IPV4:
1733 			{
1734 				rule_action->encap.vxlan.ipv4.sa =
1735 					rte_ntohl(spec.ipv4.hdr.src_addr);
1736 				rule_action->encap.vxlan.ipv4.da =
1737 					rte_ntohl(spec.ipv4.hdr.dst_addr);
1738 				rule_action->encap.vxlan.ipv4.dscp =
1739 					spec.ipv4.hdr.type_of_service >> 2;
1740 				rule_action->encap.vxlan.ipv4.ttl =
1741 					spec.ipv4.hdr.time_to_live;
1742 				break;
1743 			}
1744 			case RTE_FLOW_ITEM_TYPE_IPV6:
1745 			{
1746 				uint32_t vtc_flow;
1747 
1748 				memcpy(&rule_action->encap.vxlan.ipv6.sa,
1749 						&spec.ipv6.hdr.src_addr,
1750 						sizeof(spec.ipv6.hdr.src_addr));
1751 				memcpy(&rule_action->encap.vxlan.ipv6.da,
1752 						&spec.ipv6.hdr.dst_addr,
1753 						sizeof(spec.ipv6.hdr.dst_addr));
1754 				vtc_flow = rte_ntohl(spec.ipv6.hdr.vtc_flow);
1755 				rule_action->encap.vxlan.ipv6.flow_label =
1756 						vtc_flow & 0xfffff;
1757 				rule_action->encap.vxlan.ipv6.dscp =
1758 						(vtc_flow >> 22) & 0x3f;
1759 				rule_action->encap.vxlan.ipv6.hop_limit =
1760 					spec.ipv6.hdr.hop_limits;
1761 				break;
1762 			}
1763 			default:
1764 				return rte_flow_error_set(error,
1765 					EINVAL,
1766 					RTE_FLOW_ERROR_TYPE_ITEM,
1767 					item,
1768 					"VXLAN ENCAP: encap item after ether should be ipv4/ipv6");
1769 			}
1770 
1771 			item++;
1772 
1773 			/* Check for UDP. */
1774 			flow_item_skip_void(&item);
1775 			status = flow_item_proto_preprocess(item, &spec, &mask,
1776 					&size, &disabled, error);
1777 			if (status)
1778 				return status;
1779 
1780 			if (item->type != RTE_FLOW_ITEM_TYPE_UDP) {
1781 				return rte_flow_error_set(error,
1782 					EINVAL,
1783 					RTE_FLOW_ERROR_TYPE_ITEM,
1784 					item,
1785 					"VXLAN ENCAP: encap item after ipv4/ipv6 should be udp");
1786 			}
1787 			rule_action->encap.vxlan.udp.sp =
1788 				rte_ntohs(spec.udp.hdr.src_port);
1789 			rule_action->encap.vxlan.udp.dp =
1790 				rte_ntohs(spec.udp.hdr.dst_port);
1791 
1792 			item++;
1793 
1794 			/* Check for VXLAN. */
1795 			flow_item_skip_void(&item);
1796 			status = flow_item_proto_preprocess(item, &spec, &mask,
1797 					&size, &disabled, error);
1798 			if (status)
1799 				return status;
1800 
1801 			if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
1802 				return rte_flow_error_set(error,
1803 					EINVAL,
1804 					RTE_FLOW_ERROR_TYPE_ITEM,
1805 					item,
1806 					"VXLAN ENCAP: encap item after udp should be vxlan");
1807 			}
1808 			rule_action->encap.vxlan.vxlan.vni =
1809 				(spec.vxlan.vni[0] << 16U |
1810 					spec.vxlan.vni[1] << 8U
1811 					| spec.vxlan.vni[2]);
1812 
1813 			item++;
1814 
1815 			/* Check for END. */
1816 			flow_item_skip_void(&item);
1817 
1818 			if (item->type != RTE_FLOW_ITEM_TYPE_END)
1819 				return rte_flow_error_set(error,
1820 					EINVAL,
1821 					RTE_FLOW_ERROR_TYPE_ITEM,
1822 					item,
1823 					"VXLAN ENCAP: expecting END item");
1824 
1825 			rule_action->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
1826 			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
1827 			break;
1828 		} /* RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP */
1829 
1830 		default:
1831 			return -ENOTSUP;
1832 		}
1833 	}
1834 
1835 	if (n_jump_queue_rss_drop == 0)
1836 		return rte_flow_error_set(error,
1837 			EINVAL,
1838 			RTE_FLOW_ERROR_TYPE_ACTION,
1839 			action,
1840 			"Flow does not have any terminating action");
1841 
1842 	return 0;
1843 }
1844 
1845 static int
pmd_flow_validate(struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item item[],const struct rte_flow_action action[],struct rte_flow_error * error)1846 pmd_flow_validate(struct rte_eth_dev *dev,
1847 		const struct rte_flow_attr *attr,
1848 		const struct rte_flow_item item[],
1849 		const struct rte_flow_action action[],
1850 		struct rte_flow_error *error)
1851 {
1852 	struct softnic_table_rule_match rule_match;
1853 	struct softnic_table_rule_action rule_action;
1854 
1855 	struct pmd_internals *softnic = dev->data->dev_private;
1856 	struct pipeline *pipeline;
1857 	struct softnic_table *table;
1858 	const char *pipeline_name = NULL;
1859 	uint32_t table_id = 0;
1860 	int status;
1861 
1862 	/* Check input parameters. */
1863 	if (attr == NULL)
1864 		return rte_flow_error_set(error,
1865 				EINVAL,
1866 				RTE_FLOW_ERROR_TYPE_ATTR,
1867 				NULL, "Null attr");
1868 
1869 	if (item == NULL)
1870 		return rte_flow_error_set(error,
1871 				EINVAL,
1872 				RTE_FLOW_ERROR_TYPE_ITEM,
1873 				NULL,
1874 				"Null item");
1875 
1876 	if (action == NULL)
1877 		return rte_flow_error_set(error,
1878 				EINVAL,
1879 				RTE_FLOW_ERROR_TYPE_ACTION,
1880 				NULL,
1881 				"Null action");
1882 
1883 	/* Identify the pipeline table to add this flow to. */
1884 	status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
1885 					&table_id, error);
1886 	if (status)
1887 		return status;
1888 
1889 	pipeline = softnic_pipeline_find(softnic, pipeline_name);
1890 	if (pipeline == NULL)
1891 		return rte_flow_error_set(error,
1892 				EINVAL,
1893 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1894 				NULL,
1895 				"Invalid pipeline name");
1896 
1897 	if (table_id >= pipeline->n_tables)
1898 		return rte_flow_error_set(error,
1899 				EINVAL,
1900 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
1901 				NULL,
1902 				"Invalid pipeline table ID");
1903 
1904 	table = &pipeline->table[table_id];
1905 
1906 	/* Rule match. */
1907 	memset(&rule_match, 0, sizeof(rule_match));
1908 	status = flow_rule_match_get(softnic,
1909 			pipeline,
1910 			table,
1911 			attr,
1912 			item,
1913 			&rule_match,
1914 			error);
1915 	if (status)
1916 		return status;
1917 
1918 	/* Rule action. */
1919 	memset(&rule_action, 0, sizeof(rule_action));
1920 	status = flow_rule_action_get(softnic,
1921 		pipeline,
1922 		table,
1923 		attr,
1924 		action,
1925 		&rule_action,
1926 		error);
1927 	if (status)
1928 		return status;
1929 
1930 	return 0;
1931 }
1932 
1933 static struct softnic_mtr *
flow_action_meter_get(struct pmd_internals * softnic,const struct rte_flow_action * action)1934 flow_action_meter_get(struct pmd_internals *softnic,
1935 	const struct rte_flow_action *action)
1936 {
1937 	for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++)
1938 		if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
1939 			const struct rte_flow_action_meter *conf = action->conf;
1940 
1941 			if (conf == NULL)
1942 				return NULL;
1943 
1944 			return softnic_mtr_find(softnic, conf->mtr_id);
1945 		}
1946 
1947 	return NULL;
1948 }
1949 
1950 static void
flow_meter_owner_reset(struct pmd_internals * softnic,struct rte_flow * flow)1951 flow_meter_owner_reset(struct pmd_internals *softnic,
1952 	struct rte_flow *flow)
1953 {
1954 	struct softnic_mtr_list *ml = &softnic->mtr.mtrs;
1955 	struct softnic_mtr *m;
1956 
1957 	TAILQ_FOREACH(m, ml, node)
1958 		if (m->flow == flow) {
1959 			m->flow = NULL;
1960 			break;
1961 		}
1962 }
1963 
1964 static void
flow_meter_owner_set(struct pmd_internals * softnic,struct rte_flow * flow,struct softnic_mtr * mtr)1965 flow_meter_owner_set(struct pmd_internals *softnic,
1966 	struct rte_flow *flow,
1967 	struct softnic_mtr *mtr)
1968 {
1969 	/* Reset current flow meter  */
1970 	flow_meter_owner_reset(softnic, flow);
1971 
1972 	/* Set new flow meter */
1973 	mtr->flow = flow;
1974 }
1975 
1976 static int
is_meter_action_enable(struct pmd_internals * softnic,struct softnic_table * table)1977 is_meter_action_enable(struct pmd_internals *softnic,
1978 	struct softnic_table *table)
1979 {
1980 	struct softnic_table_action_profile *profile =
1981 		softnic_table_action_profile_find(softnic,
1982 			table->params.action_profile_name);
1983 	struct softnic_table_action_profile_params *params = &profile->params;
1984 
1985 	return (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) ? 1 : 0;
1986 }
1987 
1988 static struct rte_flow *
pmd_flow_create(struct rte_eth_dev * dev,const struct rte_flow_attr * attr,const struct rte_flow_item item[],const struct rte_flow_action action[],struct rte_flow_error * error)1989 pmd_flow_create(struct rte_eth_dev *dev,
1990 	const struct rte_flow_attr *attr,
1991 	const struct rte_flow_item item[],
1992 	const struct rte_flow_action action[],
1993 	struct rte_flow_error *error)
1994 {
1995 	struct softnic_table_rule_match rule_match;
1996 	struct softnic_table_rule_action rule_action;
1997 	void *rule_data;
1998 
1999 	struct pmd_internals *softnic = dev->data->dev_private;
2000 	struct pipeline *pipeline;
2001 	struct softnic_table *table;
2002 	struct rte_flow *flow;
2003 	struct softnic_mtr *mtr;
2004 	const char *pipeline_name = NULL;
2005 	uint32_t table_id = 0;
2006 	int new_flow, status;
2007 
2008 	/* Check input parameters. */
2009 	if (attr == NULL) {
2010 		rte_flow_error_set(error,
2011 			EINVAL,
2012 			RTE_FLOW_ERROR_TYPE_ATTR,
2013 			NULL,
2014 			"Null attr");
2015 		return NULL;
2016 	}
2017 
2018 	if (item == NULL) {
2019 		rte_flow_error_set(error,
2020 			EINVAL,
2021 			RTE_FLOW_ERROR_TYPE_ITEM,
2022 			NULL,
2023 			"Null item");
2024 		return NULL;
2025 	}
2026 
2027 	if (action == NULL) {
2028 		rte_flow_error_set(error,
2029 			EINVAL,
2030 			RTE_FLOW_ERROR_TYPE_ACTION,
2031 			NULL,
2032 			"Null action");
2033 		return NULL;
2034 	}
2035 
2036 	/* Identify the pipeline table to add this flow to. */
2037 	status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
2038 					&table_id, error);
2039 	if (status)
2040 		return NULL;
2041 
2042 	pipeline = softnic_pipeline_find(softnic, pipeline_name);
2043 	if (pipeline == NULL) {
2044 		rte_flow_error_set(error,
2045 			EINVAL,
2046 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2047 			NULL,
2048 			"Invalid pipeline name");
2049 		return NULL;
2050 	}
2051 
2052 	if (table_id >= pipeline->n_tables) {
2053 		rte_flow_error_set(error,
2054 			EINVAL,
2055 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2056 			NULL,
2057 			"Invalid pipeline table ID");
2058 		return NULL;
2059 	}
2060 
2061 	table = &pipeline->table[table_id];
2062 
2063 	/* Rule match. */
2064 	memset(&rule_match, 0, sizeof(rule_match));
2065 	status = flow_rule_match_get(softnic,
2066 		pipeline,
2067 		table,
2068 		attr,
2069 		item,
2070 		&rule_match,
2071 		error);
2072 	if (status)
2073 		return NULL;
2074 
2075 	/* Rule action. */
2076 	memset(&rule_action, 0, sizeof(rule_action));
2077 	status = flow_rule_action_get(softnic,
2078 		pipeline,
2079 		table,
2080 		attr,
2081 		action,
2082 		&rule_action,
2083 		error);
2084 	if (status)
2085 		return NULL;
2086 
2087 	/* Flow find/allocate. */
2088 	new_flow = 0;
2089 	flow = softnic_flow_find(table, &rule_match);
2090 	if (flow == NULL) {
2091 		new_flow = 1;
2092 		flow = calloc(1, sizeof(struct rte_flow));
2093 		if (flow == NULL) {
2094 			rte_flow_error_set(error,
2095 				ENOMEM,
2096 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2097 				NULL,
2098 				"Not enough memory for new flow");
2099 			return NULL;
2100 		}
2101 	}
2102 
2103 	/* Rule add. */
2104 	status = softnic_pipeline_table_rule_add(softnic,
2105 		pipeline_name,
2106 		table_id,
2107 		&rule_match,
2108 		&rule_action,
2109 		&rule_data);
2110 	if (status) {
2111 		if (new_flow)
2112 			free(flow);
2113 
2114 		rte_flow_error_set(error,
2115 			EINVAL,
2116 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2117 			NULL,
2118 			"Pipeline table rule add failed");
2119 		return NULL;
2120 	}
2121 
2122 	/* Flow fill in. */
2123 	memcpy(&flow->match, &rule_match, sizeof(rule_match));
2124 	memcpy(&flow->action, &rule_action, sizeof(rule_action));
2125 	flow->data = rule_data;
2126 	flow->pipeline = pipeline;
2127 	flow->table_id = table_id;
2128 
2129 	mtr = flow_action_meter_get(softnic, action);
2130 	if (mtr)
2131 		flow_meter_owner_set(softnic, flow, mtr);
2132 
2133 	/* Flow add to list. */
2134 	if (new_flow)
2135 		TAILQ_INSERT_TAIL(&table->flows, flow, node);
2136 
2137 	return flow;
2138 }
2139 
2140 static int
pmd_flow_destroy(struct rte_eth_dev * dev,struct rte_flow * flow,struct rte_flow_error * error)2141 pmd_flow_destroy(struct rte_eth_dev *dev,
2142 	struct rte_flow *flow,
2143 	struct rte_flow_error *error)
2144 {
2145 	struct pmd_internals *softnic = dev->data->dev_private;
2146 	struct softnic_table *table;
2147 	int status;
2148 
2149 	/* Check input parameters. */
2150 	if (flow == NULL)
2151 		return rte_flow_error_set(error,
2152 			EINVAL,
2153 			RTE_FLOW_ERROR_TYPE_HANDLE,
2154 			NULL,
2155 			"Null flow");
2156 
2157 	table = &flow->pipeline->table[flow->table_id];
2158 
2159 	/* Rule delete. */
2160 	status = softnic_pipeline_table_rule_delete(softnic,
2161 		flow->pipeline->name,
2162 		flow->table_id,
2163 		&flow->match);
2164 	if (status)
2165 		return rte_flow_error_set(error,
2166 			EINVAL,
2167 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2168 			NULL,
2169 			"Pipeline table rule delete failed");
2170 
2171 	/* Update dependencies */
2172 	if (is_meter_action_enable(softnic, table))
2173 		flow_meter_owner_reset(softnic, flow);
2174 
2175 	/* Flow delete. */
2176 	TAILQ_REMOVE(&table->flows, flow, node);
2177 	free(flow);
2178 
2179 	return 0;
2180 }
2181 
2182 static int
pmd_flow_flush(struct rte_eth_dev * dev,struct rte_flow_error * error)2183 pmd_flow_flush(struct rte_eth_dev *dev,
2184 	struct rte_flow_error *error)
2185 {
2186 	struct pmd_internals *softnic = dev->data->dev_private;
2187 	struct pipeline *pipeline;
2188 	int fail_to_del_rule = 0;
2189 	uint32_t i;
2190 
2191 	TAILQ_FOREACH(pipeline, &softnic->pipeline_list, node) {
2192 		/* Remove all the flows added to the tables. */
2193 		for (i = 0; i < pipeline->n_tables; i++) {
2194 			struct softnic_table *table = &pipeline->table[i];
2195 			struct rte_flow *flow;
2196 			void *temp;
2197 			int status;
2198 
2199 			TAILQ_FOREACH_SAFE(flow, &table->flows, node, temp) {
2200 				/* Rule delete. */
2201 				status = softnic_pipeline_table_rule_delete
2202 						(softnic,
2203 						pipeline->name,
2204 						i,
2205 						&flow->match);
2206 				if (status)
2207 					fail_to_del_rule = 1;
2208 				/* Update dependencies */
2209 				if (is_meter_action_enable(softnic, table))
2210 					flow_meter_owner_reset(softnic, flow);
2211 
2212 				/* Flow delete. */
2213 				TAILQ_REMOVE(&table->flows, flow, node);
2214 				free(flow);
2215 			}
2216 		}
2217 	}
2218 
2219 	if (fail_to_del_rule)
2220 		return rte_flow_error_set(error,
2221 			EINVAL,
2222 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2223 			NULL,
2224 			"Some of the rules could not be deleted");
2225 
2226 	return 0;
2227 }
2228 
2229 static int
pmd_flow_query(struct rte_eth_dev * dev __rte_unused,struct rte_flow * flow,const struct rte_flow_action * action __rte_unused,void * data,struct rte_flow_error * error)2230 pmd_flow_query(struct rte_eth_dev *dev __rte_unused,
2231 	struct rte_flow *flow,
2232 	const struct rte_flow_action *action __rte_unused,
2233 	void *data,
2234 	struct rte_flow_error *error)
2235 {
2236 	struct rte_table_action_stats_counters stats;
2237 	struct softnic_table *table;
2238 	struct rte_flow_query_count *flow_stats = data;
2239 	int status;
2240 
2241 	/* Check input parameters. */
2242 	if (flow == NULL)
2243 		return rte_flow_error_set(error,
2244 			EINVAL,
2245 			RTE_FLOW_ERROR_TYPE_HANDLE,
2246 			NULL,
2247 			"Null flow");
2248 
2249 	if (data == NULL)
2250 		return rte_flow_error_set(error,
2251 			EINVAL,
2252 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2253 			NULL,
2254 			"Null data");
2255 
2256 	table = &flow->pipeline->table[flow->table_id];
2257 
2258 	/* Rule stats read. */
2259 	status = rte_table_action_stats_read(table->a,
2260 		flow->data,
2261 		&stats,
2262 		flow_stats->reset);
2263 	if (status)
2264 		return rte_flow_error_set(error,
2265 			EINVAL,
2266 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2267 			NULL,
2268 			"Pipeline table rule stats read failed");
2269 
2270 	/* Fill in flow stats. */
2271 	flow_stats->hits_set =
2272 		(table->ap->params.stats.n_packets_enabled) ? 1 : 0;
2273 	flow_stats->bytes_set =
2274 		(table->ap->params.stats.n_bytes_enabled) ? 1 : 0;
2275 	flow_stats->hits = stats.n_packets;
2276 	flow_stats->bytes = stats.n_bytes;
2277 
2278 	return 0;
2279 }
2280 
2281 const struct rte_flow_ops pmd_flow_ops = {
2282 	.validate = pmd_flow_validate,
2283 	.create = pmd_flow_create,
2284 	.destroy = pmd_flow_destroy,
2285 	.flush = pmd_flow_flush,
2286 	.query = pmd_flow_query,
2287 	.isolate = NULL,
2288 };
2289