xref: /dpdk/app/test-flow-perf/actions_gen.c (revision 4e2cf9af)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020 Mellanox Technologies, Ltd
3  *
4  * The file contains the implementations of actions generators.
5  * Each generator is responsible for preparing it's action instance
6  * and initializing it with needed data.
7  */
8 
9 #include <sys/types.h>
10 #include <rte_malloc.h>
11 #include <rte_flow.h>
12 #include <rte_ethdev.h>
13 #include <rte_vxlan.h>
14 #include <rte_gtp.h>
15 
16 #include "actions_gen.h"
17 #include "flow_gen.h"
18 #include "config.h"
19 
20 
21 /* Storage for additional parameters for actions */
22 struct additional_para {
23 	uint16_t queue;
24 	uint16_t next_table;
25 	uint16_t *queues;
26 	uint16_t queues_number;
27 	uint32_t counter;
28 	uint64_t encap_data;
29 	uint64_t decap_data;
30 };
31 
32 /* Storage for struct rte_flow_action_raw_encap including external data. */
33 struct action_raw_encap_data {
34 	struct rte_flow_action_raw_encap conf;
35 	uint8_t data[128];
36 	uint8_t preserve[128];
37 	uint16_t idx;
38 };
39 
40 /* Storage for struct rte_flow_action_raw_decap including external data. */
41 struct action_raw_decap_data {
42 	struct rte_flow_action_raw_decap conf;
43 	uint8_t data[128];
44 	uint16_t idx;
45 };
46 
47 /* Storage for struct rte_flow_action_rss including external data. */
48 struct action_rss_data {
49 	struct rte_flow_action_rss conf;
50 	uint8_t key[40];
51 	uint16_t queue[128];
52 };
53 
54 static void
55 add_mark(struct rte_flow_action *actions,
56 	uint8_t actions_counter,
57 	struct additional_para para)
58 {
59 	static struct rte_flow_action_mark mark_action;
60 	uint32_t counter = para.counter;
61 
62 	do {
63 		/* Random values from 1 to 256 */
64 		mark_action.id = (counter % 255) + 1;
65 	} while (0);
66 
67 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_MARK;
68 	actions[actions_counter].conf = &mark_action;
69 }
70 
71 static void
72 add_queue(struct rte_flow_action *actions,
73 	uint8_t actions_counter,
74 	struct additional_para para)
75 {
76 	static struct rte_flow_action_queue queue_action;
77 
78 	do {
79 		queue_action.index = para.queue;
80 	} while (0);
81 
82 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_QUEUE;
83 	actions[actions_counter].conf = &queue_action;
84 }
85 
86 static void
87 add_jump(struct rte_flow_action *actions,
88 	uint8_t actions_counter,
89 	struct additional_para para)
90 {
91 	static struct rte_flow_action_jump jump_action;
92 
93 	do {
94 		jump_action.group = para.next_table;
95 	} while (0);
96 
97 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_JUMP;
98 	actions[actions_counter].conf = &jump_action;
99 }
100 
101 static void
102 add_rss(struct rte_flow_action *actions,
103 	uint8_t actions_counter,
104 	struct additional_para para)
105 {
106 	static struct rte_flow_action_rss *rss_action;
107 	static struct action_rss_data *rss_data;
108 
109 	uint16_t queue;
110 
111 	if (rss_data == NULL)
112 		rss_data = rte_malloc("rss_data",
113 			sizeof(struct action_rss_data), 0);
114 
115 	if (rss_data == NULL)
116 		rte_exit(EXIT_FAILURE, "No Memory available!");
117 
118 	*rss_data = (struct action_rss_data){
119 		.conf = (struct rte_flow_action_rss){
120 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
121 			.level = 0,
122 			.types = GET_RSS_HF(),
123 			.key_len = sizeof(rss_data->key),
124 			.queue_num = para.queues_number,
125 			.key = rss_data->key,
126 			.queue = rss_data->queue,
127 		},
128 		.key = { 1 },
129 		.queue = { 0 },
130 	};
131 
132 	for (queue = 0; queue < para.queues_number; queue++)
133 		rss_data->queue[queue] = para.queues[queue];
134 
135 	rss_action = &rss_data->conf;
136 
137 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_RSS;
138 	actions[actions_counter].conf = rss_action;
139 }
140 
141 static void
142 add_set_meta(struct rte_flow_action *actions,
143 	uint8_t actions_counter,
144 	__rte_unused struct additional_para para)
145 {
146 	static struct rte_flow_action_set_meta meta_action;
147 
148 	do {
149 		meta_action.data = RTE_BE32(META_DATA);
150 		meta_action.mask = RTE_BE32(0xffffffff);
151 	} while (0);
152 
153 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_META;
154 	actions[actions_counter].conf = &meta_action;
155 }
156 
157 static void
158 add_set_tag(struct rte_flow_action *actions,
159 	uint8_t actions_counter,
160 	__rte_unused struct additional_para para)
161 {
162 	static struct rte_flow_action_set_tag tag_action;
163 
164 	do {
165 		tag_action.data = RTE_BE32(META_DATA);
166 		tag_action.mask = RTE_BE32(0xffffffff);
167 		tag_action.index = TAG_INDEX;
168 	} while (0);
169 
170 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TAG;
171 	actions[actions_counter].conf = &tag_action;
172 }
173 
174 static void
175 add_port_id(struct rte_flow_action *actions,
176 	uint8_t actions_counter,
177 	__rte_unused struct additional_para para)
178 {
179 	static struct rte_flow_action_port_id port_id;
180 
181 	do {
182 		port_id.id = PORT_ID_DST;
183 	} while (0);
184 
185 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_PORT_ID;
186 	actions[actions_counter].conf = &port_id;
187 }
188 
189 static void
190 add_drop(struct rte_flow_action *actions,
191 	uint8_t actions_counter,
192 	__rte_unused struct additional_para para)
193 {
194 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DROP;
195 }
196 
197 static void
198 add_count(struct rte_flow_action *actions,
199 	uint8_t actions_counter,
200 	__rte_unused struct additional_para para)
201 {
202 	static struct rte_flow_action_count count_action;
203 
204 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_COUNT;
205 	actions[actions_counter].conf = &count_action;
206 }
207 
208 static void
209 add_set_src_mac(struct rte_flow_action *actions,
210 	uint8_t actions_counter,
211 	__rte_unused struct additional_para para)
212 {
213 	static struct rte_flow_action_set_mac set_mac;
214 	uint32_t mac = para.counter;
215 	uint16_t i;
216 
217 	/* Fixed value */
218 	if (FIXED_VALUES)
219 		mac = 1;
220 
221 	/* Mac address to be set is random each time */
222 	for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
223 		set_mac.mac_addr[i] = mac & 0xff;
224 		mac = mac >> 8;
225 	}
226 
227 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_MAC_SRC;
228 	actions[actions_counter].conf = &set_mac;
229 }
230 
231 static void
232 add_set_dst_mac(struct rte_flow_action *actions,
233 	uint8_t actions_counter,
234 	__rte_unused struct additional_para para)
235 {
236 	static struct rte_flow_action_set_mac set_mac;
237 	uint32_t mac = para.counter;
238 	uint16_t i;
239 
240 	/* Fixed value */
241 	if (FIXED_VALUES)
242 		mac = 1;
243 
244 	/* Mac address to be set is random each time */
245 	for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
246 		set_mac.mac_addr[i] = mac & 0xff;
247 		mac = mac >> 8;
248 	}
249 
250 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_MAC_DST;
251 	actions[actions_counter].conf = &set_mac;
252 }
253 
254 static void
255 add_set_src_ipv4(struct rte_flow_action *actions,
256 	uint8_t actions_counter,
257 	__rte_unused struct additional_para para)
258 {
259 	static struct rte_flow_action_set_ipv4 set_ipv4;
260 	uint32_t ip = para.counter;
261 
262 	/* Fixed value */
263 	if (FIXED_VALUES)
264 		ip = 1;
265 
266 	/* IPv4 value to be set is random each time */
267 	set_ipv4.ipv4_addr = RTE_BE32(ip + 1);
268 
269 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC;
270 	actions[actions_counter].conf = &set_ipv4;
271 }
272 
273 static void
274 add_set_dst_ipv4(struct rte_flow_action *actions,
275 	uint8_t actions_counter,
276 	__rte_unused struct additional_para para)
277 {
278 	static struct rte_flow_action_set_ipv4 set_ipv4;
279 	uint32_t ip = para.counter;
280 
281 	/* Fixed value */
282 	if (FIXED_VALUES)
283 		ip = 1;
284 
285 	/* IPv4 value to be set is random each time */
286 	set_ipv4.ipv4_addr = RTE_BE32(ip + 1);
287 
288 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_DST;
289 	actions[actions_counter].conf = &set_ipv4;
290 }
291 
292 static void
293 add_set_src_ipv6(struct rte_flow_action *actions,
294 	uint8_t actions_counter,
295 	__rte_unused struct additional_para para)
296 {
297 	static struct rte_flow_action_set_ipv6 set_ipv6;
298 	uint32_t ipv6 = para.counter;
299 	uint8_t i;
300 
301 	/* Fixed value */
302 	if (FIXED_VALUES)
303 		ipv6 = 1;
304 
305 	/* IPv6 value to set is random each time */
306 	for (i = 0; i < 16; i++) {
307 		set_ipv6.ipv6_addr[i] = ipv6 & 0xff;
308 		ipv6 = ipv6 >> 8;
309 	}
310 
311 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC;
312 	actions[actions_counter].conf = &set_ipv6;
313 }
314 
315 static void
316 add_set_dst_ipv6(struct rte_flow_action *actions,
317 	uint8_t actions_counter,
318 	__rte_unused struct additional_para para)
319 {
320 	static struct rte_flow_action_set_ipv6 set_ipv6;
321 	uint32_t ipv6 = para.counter;
322 	uint8_t i;
323 
324 	/* Fixed value */
325 	if (FIXED_VALUES)
326 		ipv6 = 1;
327 
328 	/* IPv6 value to set is random each time */
329 	for (i = 0; i < 16; i++) {
330 		set_ipv6.ipv6_addr[i] = ipv6 & 0xff;
331 		ipv6 = ipv6 >> 8;
332 	}
333 
334 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_DST;
335 	actions[actions_counter].conf = &set_ipv6;
336 }
337 
338 static void
339 add_set_src_tp(struct rte_flow_action *actions,
340 	uint8_t actions_counter,
341 	__rte_unused struct additional_para para)
342 {
343 	static struct rte_flow_action_set_tp set_tp;
344 	uint32_t tp = para.counter;
345 
346 	/* Fixed value */
347 	if (FIXED_VALUES)
348 		tp = 100;
349 
350 	/* TP src port is random each time */
351 	tp = tp % 0xffff;
352 
353 	set_tp.port = RTE_BE16(tp & 0xffff);
354 
355 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TP_SRC;
356 	actions[actions_counter].conf = &set_tp;
357 }
358 
359 static void
360 add_set_dst_tp(struct rte_flow_action *actions,
361 	uint8_t actions_counter,
362 	__rte_unused struct additional_para para)
363 {
364 	static struct rte_flow_action_set_tp set_tp;
365 	uint32_t tp = para.counter;
366 
367 	/* Fixed value */
368 	if (FIXED_VALUES)
369 		tp = 100;
370 
371 	/* TP src port is random each time */
372 	if (tp > 0xffff)
373 		tp = tp >> 16;
374 
375 	set_tp.port = RTE_BE16(tp & 0xffff);
376 
377 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TP_DST;
378 	actions[actions_counter].conf = &set_tp;
379 }
380 
381 static void
382 add_inc_tcp_ack(struct rte_flow_action *actions,
383 	uint8_t actions_counter,
384 	__rte_unused struct additional_para para)
385 {
386 	static rte_be32_t value;
387 	uint32_t ack_value = para.counter;
388 
389 	/* Fixed value */
390 	if (FIXED_VALUES)
391 		ack_value = 1;
392 
393 	value = RTE_BE32(ack_value);
394 
395 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_INC_TCP_ACK;
396 	actions[actions_counter].conf = &value;
397 }
398 
399 static void
400 add_dec_tcp_ack(struct rte_flow_action *actions,
401 	uint8_t actions_counter,
402 	__rte_unused struct additional_para para)
403 {
404 	static rte_be32_t value;
405 	uint32_t ack_value = para.counter;
406 
407 	/* Fixed value */
408 	if (FIXED_VALUES)
409 		ack_value = 1;
410 
411 	value = RTE_BE32(ack_value);
412 
413 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK;
414 	actions[actions_counter].conf = &value;
415 }
416 
417 static void
418 add_inc_tcp_seq(struct rte_flow_action *actions,
419 	uint8_t actions_counter,
420 	__rte_unused struct additional_para para)
421 {
422 	static rte_be32_t value;
423 	uint32_t seq_value = para.counter;
424 
425 	/* Fixed value */
426 	if (FIXED_VALUES)
427 		seq_value = 1;
428 
429 	value = RTE_BE32(seq_value);
430 
431 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ;
432 	actions[actions_counter].conf = &value;
433 }
434 
435 static void
436 add_dec_tcp_seq(struct rte_flow_action *actions,
437 	uint8_t actions_counter,
438 	__rte_unused struct additional_para para)
439 {
440 	static rte_be32_t value;
441 	uint32_t seq_value = para.counter;
442 
443 	/* Fixed value */
444 	if (FIXED_VALUES)
445 		seq_value = 1;
446 
447 	value	= RTE_BE32(seq_value);
448 
449 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ;
450 	actions[actions_counter].conf = &value;
451 }
452 
453 static void
454 add_set_ttl(struct rte_flow_action *actions,
455 	uint8_t actions_counter,
456 	__rte_unused struct additional_para para)
457 {
458 	static struct rte_flow_action_set_ttl set_ttl;
459 	uint32_t ttl_value = para.counter;
460 
461 	/* Fixed value */
462 	if (FIXED_VALUES)
463 		ttl_value = 1;
464 
465 	/* Set ttl to random value each time */
466 	ttl_value = ttl_value % 0xff;
467 
468 	set_ttl.ttl_value = ttl_value;
469 
470 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TTL;
471 	actions[actions_counter].conf = &set_ttl;
472 }
473 
474 static void
475 add_dec_ttl(struct rte_flow_action *actions,
476 	uint8_t actions_counter,
477 	__rte_unused struct additional_para para)
478 {
479 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TTL;
480 }
481 
482 static void
483 add_set_ipv4_dscp(struct rte_flow_action *actions,
484 	uint8_t actions_counter,
485 	__rte_unused struct additional_para para)
486 {
487 	static struct rte_flow_action_set_dscp set_dscp;
488 	uint32_t dscp_value = para.counter;
489 
490 	/* Fixed value */
491 	if (FIXED_VALUES)
492 		dscp_value = 1;
493 
494 	/* Set dscp to random value each time */
495 	dscp_value = dscp_value % 0xff;
496 
497 	set_dscp.dscp = dscp_value;
498 
499 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP;
500 	actions[actions_counter].conf = &set_dscp;
501 }
502 
503 static void
504 add_set_ipv6_dscp(struct rte_flow_action *actions,
505 	uint8_t actions_counter,
506 	__rte_unused struct additional_para para)
507 {
508 	static struct rte_flow_action_set_dscp set_dscp;
509 	uint32_t dscp_value = para.counter;
510 
511 	/* Fixed value */
512 	if (FIXED_VALUES)
513 		dscp_value = 1;
514 
515 	/* Set dscp to random value each time */
516 	dscp_value = dscp_value % 0xff;
517 
518 	set_dscp.dscp = dscp_value;
519 
520 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP;
521 	actions[actions_counter].conf = &set_dscp;
522 }
523 
524 static void
525 add_flag(struct rte_flow_action *actions,
526 	uint8_t actions_counter,
527 	__rte_unused struct additional_para para)
528 {
529 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_FLAG;
530 }
531 
532 static void
533 add_ether_header(uint8_t **header, uint64_t data,
534 	__rte_unused struct additional_para para)
535 {
536 	struct rte_flow_item_eth eth_item;
537 
538 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_ETH)))
539 		return;
540 
541 	memset(&eth_item, 0, sizeof(struct rte_flow_item_eth));
542 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VLAN))
543 		eth_item.type = RTE_BE16(RTE_ETHER_TYPE_VLAN);
544 	else if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV4))
545 		eth_item.type = RTE_BE16(RTE_ETHER_TYPE_IPV4);
546 	else if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV6))
547 		eth_item.type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
548 	memcpy(*header, &eth_item, sizeof(eth_item));
549 	*header += sizeof(eth_item);
550 }
551 
552 static void
553 add_vlan_header(uint8_t **header, uint64_t data,
554 	__rte_unused struct additional_para para)
555 {
556 	struct rte_flow_item_vlan vlan_item;
557 	uint16_t vlan_value;
558 
559 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VLAN)))
560 		return;
561 
562 	vlan_value = VLAN_VALUE;
563 
564 	memset(&vlan_item, 0, sizeof(struct rte_flow_item_vlan));
565 	vlan_item.tci = RTE_BE16(vlan_value);
566 
567 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV4))
568 		vlan_item.inner_type = RTE_BE16(RTE_ETHER_TYPE_IPV4);
569 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV6))
570 		vlan_item.inner_type = RTE_BE16(RTE_ETHER_TYPE_IPV6);
571 	memcpy(*header, &vlan_item, sizeof(vlan_item));
572 	*header += sizeof(vlan_item);
573 }
574 
575 static void
576 add_ipv4_header(uint8_t **header, uint64_t data,
577 	struct additional_para para)
578 {
579 	struct rte_flow_item_ipv4 ipv4_item;
580 	uint32_t ip_dst = para.counter;
581 
582 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV4)))
583 		return;
584 
585 	/* Fixed value */
586 	if (FIXED_VALUES)
587 		ip_dst = 1;
588 
589 	memset(&ipv4_item, 0, sizeof(struct rte_flow_item_ipv4));
590 	ipv4_item.hdr.src_addr = RTE_IPV4(127, 0, 0, 1);
591 	ipv4_item.hdr.dst_addr = RTE_BE32(ip_dst);
592 	ipv4_item.hdr.version_ihl = RTE_IPV4_VHL_DEF;
593 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_UDP))
594 		ipv4_item.hdr.next_proto_id = RTE_IP_TYPE_UDP;
595 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GRE))
596 		ipv4_item.hdr.next_proto_id = RTE_IP_TYPE_GRE;
597 	memcpy(*header, &ipv4_item, sizeof(ipv4_item));
598 	*header += sizeof(ipv4_item);
599 }
600 
601 static void
602 add_ipv6_header(uint8_t **header, uint64_t data,
603 	__rte_unused struct additional_para para)
604 {
605 	struct rte_flow_item_ipv6 ipv6_item;
606 
607 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_IPV6)))
608 		return;
609 
610 	memset(&ipv6_item, 0, sizeof(struct rte_flow_item_ipv6));
611 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_UDP))
612 		ipv6_item.hdr.proto = RTE_IP_TYPE_UDP;
613 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GRE))
614 		ipv6_item.hdr.proto = RTE_IP_TYPE_GRE;
615 	memcpy(*header, &ipv6_item, sizeof(ipv6_item));
616 	*header += sizeof(ipv6_item);
617 }
618 
619 static void
620 add_udp_header(uint8_t **header, uint64_t data,
621 	__rte_unused struct additional_para para)
622 {
623 	struct rte_flow_item_udp udp_item;
624 
625 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_UDP)))
626 		return;
627 
628 	memset(&udp_item, 0, sizeof(struct rte_flow_item_udp));
629 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN))
630 		udp_item.hdr.dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT);
631 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN_GPE))
632 		udp_item.hdr.dst_port = RTE_BE16(RTE_VXLAN_GPE_UDP_PORT);
633 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GENEVE))
634 		udp_item.hdr.dst_port = RTE_BE16(RTE_GENEVE_UDP_PORT);
635 	if (data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GTP))
636 		udp_item.hdr.dst_port = RTE_BE16(RTE_GTPU_UDP_PORT);
637 	 memcpy(*header, &udp_item, sizeof(udp_item));
638 	 *header += sizeof(udp_item);
639 }
640 
641 static void
642 add_vxlan_header(uint8_t **header, uint64_t data,
643 	struct additional_para para)
644 {
645 	struct rte_flow_item_vxlan vxlan_item;
646 	uint32_t vni_value = para.counter;
647 	uint8_t i;
648 
649 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN)))
650 		return;
651 
652 	/* Fixed value */
653 	if (FIXED_VALUES)
654 		vni_value = 1;
655 
656 	memset(&vxlan_item, 0, sizeof(struct rte_flow_item_vxlan));
657 
658 	for (i = 0; i < 3; i++)
659 		vxlan_item.vni[2 - i] = vni_value >> (i * 8);
660 	vxlan_item.flags = 0x8;
661 
662 	memcpy(*header, &vxlan_item, sizeof(vxlan_item));
663 	*header += sizeof(vxlan_item);
664 }
665 
666 static void
667 add_vxlan_gpe_header(uint8_t **header, uint64_t data,
668 	struct additional_para para)
669 {
670 	struct rte_flow_item_vxlan_gpe vxlan_gpe_item;
671 	uint32_t vni_value = para.counter;
672 	uint8_t i;
673 
674 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_VXLAN_GPE)))
675 		return;
676 
677 	/* Fixed value */
678 	if (FIXED_VALUES)
679 		vni_value = 1;
680 
681 	memset(&vxlan_gpe_item, 0, sizeof(struct rte_flow_item_vxlan_gpe));
682 
683 	for (i = 0; i < 3; i++)
684 		vxlan_gpe_item.vni[2 - i] = vni_value >> (i * 8);
685 	vxlan_gpe_item.flags = 0x0c;
686 
687 	memcpy(*header, &vxlan_gpe_item, sizeof(vxlan_gpe_item));
688 	*header += sizeof(vxlan_gpe_item);
689 }
690 
691 static void
692 add_gre_header(uint8_t **header, uint64_t data,
693 	__rte_unused struct additional_para para)
694 {
695 	struct rte_flow_item_gre gre_item;
696 
697 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GRE)))
698 		return;
699 
700 	memset(&gre_item, 0, sizeof(struct rte_flow_item_gre));
701 
702 	gre_item.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB);
703 
704 	memcpy(*header, &gre_item, sizeof(gre_item));
705 	*header += sizeof(gre_item);
706 }
707 
708 static void
709 add_geneve_header(uint8_t **header, uint64_t data,
710 	struct additional_para para)
711 {
712 	struct rte_flow_item_geneve geneve_item;
713 	uint32_t vni_value = para.counter;
714 	uint8_t i;
715 
716 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GENEVE)))
717 		return;
718 
719 	/* Fixed value */
720 	if (FIXED_VALUES)
721 		vni_value = 1;
722 
723 	memset(&geneve_item, 0, sizeof(struct rte_flow_item_geneve));
724 
725 	for (i = 0; i < 3; i++)
726 		geneve_item.vni[2 - i] = vni_value >> (i * 8);
727 
728 	memcpy(*header, &geneve_item, sizeof(geneve_item));
729 	*header += sizeof(geneve_item);
730 }
731 
732 static void
733 add_gtp_header(uint8_t **header, uint64_t data,
734 	struct additional_para para)
735 {
736 	struct rte_flow_item_gtp gtp_item;
737 	uint32_t teid_value = para.counter;
738 
739 	if (!(data & FLOW_ITEM_MASK(RTE_FLOW_ITEM_TYPE_GTP)))
740 		return;
741 
742 	/* Fixed value */
743 	if (FIXED_VALUES)
744 		teid_value = 1;
745 
746 	memset(&gtp_item, 0, sizeof(struct rte_flow_item_gtp));
747 
748 	gtp_item.teid = RTE_BE32(teid_value);
749 	gtp_item.msg_type = 255;
750 
751 	memcpy(*header, &gtp_item, sizeof(gtp_item));
752 	*header += sizeof(gtp_item);
753 }
754 
755 static const struct encap_decap_headers {
756 	void (*funct)(
757 		uint8_t **header,
758 		uint64_t data,
759 		struct additional_para para
760 		);
761 } headers[] = {
762 	{.funct = add_ether_header},
763 	{.funct = add_vlan_header},
764 	{.funct = add_ipv4_header},
765 	{.funct = add_ipv6_header},
766 	{.funct = add_udp_header},
767 	{.funct = add_vxlan_header},
768 	{.funct = add_vxlan_gpe_header},
769 	{.funct = add_gre_header},
770 	{.funct = add_geneve_header},
771 	{.funct = add_gtp_header},
772 };
773 
774 static void
775 add_raw_encap(struct rte_flow_action *actions,
776 	uint8_t actions_counter,
777 	struct additional_para para)
778 {
779 	static struct action_raw_encap_data *action_encap_data;
780 	uint64_t encap_data = para.encap_data;
781 	uint8_t *header;
782 	uint8_t i;
783 
784 	/* Avoid double allocation. */
785 	if (action_encap_data == NULL)
786 		action_encap_data = rte_malloc("encap_data",
787 			sizeof(struct action_raw_encap_data), 0);
788 
789 	/* Check if allocation failed. */
790 	if (action_encap_data == NULL)
791 		rte_exit(EXIT_FAILURE, "No Memory available!");
792 
793 	*action_encap_data = (struct action_raw_encap_data) {
794 		.conf = (struct rte_flow_action_raw_encap) {
795 			.data = action_encap_data->data,
796 		},
797 			.data = {},
798 	};
799 	header = action_encap_data->data;
800 
801 	for (i = 0; i < RTE_DIM(headers); i++)
802 		headers[i].funct(&header, encap_data, para);
803 
804 	action_encap_data->conf.size = header -
805 		action_encap_data->data;
806 
807 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
808 	actions[actions_counter].conf = &action_encap_data->conf;
809 }
810 
811 static void
812 add_raw_decap(struct rte_flow_action *actions,
813 	uint8_t actions_counter,
814 	struct additional_para para)
815 {
816 	static struct action_raw_decap_data *action_decap_data;
817 	uint64_t decap_data = para.decap_data;
818 	uint8_t *header;
819 	uint8_t i;
820 
821 	/* Avoid double allocation. */
822 	if (action_decap_data == NULL)
823 		action_decap_data = rte_malloc("decap_data",
824 			sizeof(struct action_raw_decap_data), 0);
825 
826 	/* Check if allocation failed. */
827 	if (action_decap_data == NULL)
828 		rte_exit(EXIT_FAILURE, "No Memory available!");
829 
830 	*action_decap_data = (struct action_raw_decap_data) {
831 		.conf = (struct rte_flow_action_raw_decap) {
832 			.data = action_decap_data->data,
833 		},
834 			.data = {},
835 	};
836 	header = action_decap_data->data;
837 
838 	for (i = 0; i < RTE_DIM(headers); i++)
839 		headers[i].funct(&header, decap_data, para);
840 
841 	action_decap_data->conf.size = header -
842 		action_decap_data->data;
843 
844 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_RAW_DECAP;
845 	actions[actions_counter].conf = &action_decap_data->conf;
846 }
847 
848 static void
849 add_vxlan_encap(struct rte_flow_action *actions,
850 	uint8_t actions_counter,
851 	__rte_unused struct additional_para para)
852 {
853 	static struct rte_flow_action_vxlan_encap vxlan_encap;
854 	static struct rte_flow_item items[5];
855 	static struct rte_flow_item_eth item_eth;
856 	static struct rte_flow_item_ipv4 item_ipv4;
857 	static struct rte_flow_item_udp item_udp;
858 	static struct rte_flow_item_vxlan item_vxlan;
859 	uint32_t ip_dst = para.counter;
860 
861 	/* Fixed value */
862 	if (FIXED_VALUES)
863 		ip_dst = 1;
864 
865 	items[0].spec = &item_eth;
866 	items[0].mask = &item_eth;
867 	items[0].type = RTE_FLOW_ITEM_TYPE_ETH;
868 
869 	item_ipv4.hdr.src_addr = RTE_IPV4(127, 0, 0, 1);
870 	item_ipv4.hdr.dst_addr = RTE_BE32(ip_dst);
871 	item_ipv4.hdr.version_ihl = RTE_IPV4_VHL_DEF;
872 	items[1].spec = &item_ipv4;
873 	items[1].mask = &item_ipv4;
874 	items[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
875 
876 
877 	item_udp.hdr.dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT);
878 	items[2].spec = &item_udp;
879 	items[2].mask = &item_udp;
880 	items[2].type = RTE_FLOW_ITEM_TYPE_UDP;
881 
882 
883 	item_vxlan.vni[2] = 1;
884 	items[3].spec = &item_vxlan;
885 	items[3].mask = &item_vxlan;
886 	items[3].type = RTE_FLOW_ITEM_TYPE_VXLAN;
887 
888 	items[4].type = RTE_FLOW_ITEM_TYPE_END;
889 
890 	vxlan_encap.definition = items;
891 
892 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP;
893 	actions[actions_counter].conf = &vxlan_encap;
894 }
895 
896 static void
897 add_vxlan_decap(struct rte_flow_action *actions,
898 	uint8_t actions_counter,
899 	__rte_unused struct additional_para para)
900 {
901 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
902 }
903 
904 void
905 fill_actions(struct rte_flow_action *actions, uint64_t *flow_actions,
906 	uint32_t counter, uint16_t next_table, uint16_t hairpinq,
907 	uint64_t encap_data, uint64_t decap_data)
908 {
909 	struct additional_para additional_para_data;
910 	uint8_t actions_counter = 0;
911 	uint16_t hairpin_queues[hairpinq];
912 	uint16_t queues[RXQ_NUM];
913 	uint16_t i, j;
914 
915 	for (i = 0; i < RXQ_NUM; i++)
916 		queues[i] = i;
917 
918 	for (i = 0; i < hairpinq; i++)
919 		hairpin_queues[i] = i + RXQ_NUM;
920 
921 	additional_para_data = (struct additional_para){
922 		.queue = counter % RXQ_NUM,
923 		.next_table = next_table,
924 		.queues = queues,
925 		.queues_number = RXQ_NUM,
926 		.counter = counter,
927 		.encap_data = encap_data,
928 		.decap_data = decap_data,
929 	};
930 
931 	if (hairpinq != 0) {
932 		additional_para_data.queues = hairpin_queues;
933 		additional_para_data.queues_number = hairpinq;
934 		additional_para_data.queue = (counter % hairpinq) + RXQ_NUM;
935 	}
936 
937 	static const struct actions_dict {
938 		uint64_t mask;
939 		void (*funct)(
940 			struct rte_flow_action *actions,
941 			uint8_t actions_counter,
942 			struct additional_para para
943 			);
944 	} actions_list[] = {
945 		{
946 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_MARK),
947 			.funct = add_mark,
948 		},
949 		{
950 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_COUNT),
951 			.funct = add_count,
952 		},
953 		{
954 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_META),
955 			.funct = add_set_meta,
956 		},
957 		{
958 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_TAG),
959 			.funct = add_set_tag,
960 		},
961 		{
962 			.mask = FLOW_ACTION_MASK(
963 				RTE_FLOW_ACTION_TYPE_FLAG
964 			),
965 			.funct = add_flag,
966 		},
967 		{
968 			.mask = FLOW_ACTION_MASK(
969 				RTE_FLOW_ACTION_TYPE_SET_MAC_SRC
970 			),
971 			.funct = add_set_src_mac,
972 		},
973 		{
974 			.mask = FLOW_ACTION_MASK(
975 				RTE_FLOW_ACTION_TYPE_SET_MAC_DST
976 			),
977 			.funct = add_set_dst_mac,
978 		},
979 		{
980 			.mask = FLOW_ACTION_MASK(
981 				RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC
982 			),
983 			.funct = add_set_src_ipv4,
984 		},
985 		{
986 			.mask =	FLOW_ACTION_MASK(
987 				RTE_FLOW_ACTION_TYPE_SET_IPV4_DST
988 			),
989 			.funct = add_set_dst_ipv4,
990 		},
991 		{
992 			.mask = FLOW_ACTION_MASK(
993 				RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC
994 			),
995 			.funct = add_set_src_ipv6,
996 		},
997 		{
998 			.mask = FLOW_ACTION_MASK(
999 				RTE_FLOW_ACTION_TYPE_SET_IPV6_DST
1000 			),
1001 			.funct = add_set_dst_ipv6,
1002 		},
1003 		{
1004 			.mask = FLOW_ACTION_MASK(
1005 				RTE_FLOW_ACTION_TYPE_SET_TP_SRC
1006 			),
1007 			.funct = add_set_src_tp,
1008 		},
1009 		{
1010 			.mask = FLOW_ACTION_MASK(
1011 				RTE_FLOW_ACTION_TYPE_SET_TP_DST
1012 			),
1013 			.funct = add_set_dst_tp,
1014 		},
1015 		{
1016 			.mask = FLOW_ACTION_MASK(
1017 				RTE_FLOW_ACTION_TYPE_INC_TCP_ACK
1018 			),
1019 			.funct = add_inc_tcp_ack,
1020 		},
1021 		{
1022 			.mask = FLOW_ACTION_MASK(
1023 				RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK
1024 			),
1025 			.funct = add_dec_tcp_ack,
1026 		},
1027 		{
1028 			.mask = FLOW_ACTION_MASK(
1029 				RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ
1030 			),
1031 			.funct = add_inc_tcp_seq,
1032 		},
1033 		{
1034 			.mask = FLOW_ACTION_MASK(
1035 				RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ
1036 			),
1037 			.funct = add_dec_tcp_seq,
1038 		},
1039 		{
1040 			.mask = FLOW_ACTION_MASK(
1041 				RTE_FLOW_ACTION_TYPE_SET_TTL
1042 			),
1043 			.funct = add_set_ttl,
1044 		},
1045 		{
1046 			.mask = FLOW_ACTION_MASK(
1047 				RTE_FLOW_ACTION_TYPE_DEC_TTL
1048 			),
1049 			.funct = add_dec_ttl,
1050 		},
1051 		{
1052 			.mask = FLOW_ACTION_MASK(
1053 				RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP
1054 			),
1055 			.funct = add_set_ipv4_dscp,
1056 		},
1057 		{
1058 			.mask = FLOW_ACTION_MASK(
1059 				RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP
1060 			),
1061 			.funct = add_set_ipv6_dscp,
1062 		},
1063 		{
1064 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_QUEUE),
1065 			.funct = add_queue,
1066 		},
1067 		{
1068 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_RSS),
1069 			.funct = add_rss,
1070 		},
1071 		{
1072 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_JUMP),
1073 			.funct = add_jump,
1074 		},
1075 		{
1076 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_PORT_ID),
1077 			.funct = add_port_id
1078 		},
1079 		{
1080 			.mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_DROP),
1081 			.funct = add_drop,
1082 		},
1083 		{
1084 			.mask = HAIRPIN_QUEUE_ACTION,
1085 			.funct = add_queue,
1086 		},
1087 		{
1088 			.mask = HAIRPIN_RSS_ACTION,
1089 			.funct = add_rss,
1090 		},
1091 		{
1092 			.mask = FLOW_ACTION_MASK(
1093 				RTE_FLOW_ACTION_TYPE_RAW_ENCAP
1094 			),
1095 			.funct = add_raw_encap,
1096 		},
1097 		{
1098 			.mask = FLOW_ACTION_MASK(
1099 				RTE_FLOW_ACTION_TYPE_RAW_DECAP
1100 			),
1101 			.funct = add_raw_decap,
1102 		},
1103 		{
1104 			.mask = FLOW_ACTION_MASK(
1105 				RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP
1106 			),
1107 			.funct = add_vxlan_encap,
1108 		},
1109 		{
1110 			.mask = FLOW_ACTION_MASK(
1111 				RTE_FLOW_ACTION_TYPE_VXLAN_DECAP
1112 			),
1113 			.funct = add_vxlan_decap,
1114 		},
1115 	};
1116 
1117 	for (j = 0; j < MAX_ACTIONS_NUM; j++) {
1118 		if (flow_actions[j] == 0)
1119 			break;
1120 		for (i = 0; i < RTE_DIM(actions_list); i++) {
1121 			if ((flow_actions[j] &
1122 				actions_list[i].mask) == 0)
1123 				continue;
1124 			actions_list[i].funct(
1125 				actions, actions_counter++,
1126 				additional_para_data
1127 			);
1128 			break;
1129 		}
1130 	}
1131 	actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_END;
1132 }
1133