99e47bf786d784e67a161c3ad69a74689e87eabb
[dpdk.git] / app / test-flow-perf / actions_gen.c
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
14 #include "actions_gen.h"
15 #include "flow_gen.h"
16 #include "config.h"
17
18 /* Storage for additional parameters for actions */
19 struct additional_para {
20         uint16_t queue;
21         uint16_t next_table;
22         uint16_t *queues;
23         uint16_t queues_number;
24         uint32_t counter;
25 };
26
27 /* Storage for struct rte_flow_action_rss including external data. */
28 struct action_rss_data {
29         struct rte_flow_action_rss conf;
30         uint8_t key[40];
31         uint16_t queue[128];
32 };
33
34 static void
35 add_mark(struct rte_flow_action *actions,
36         uint8_t actions_counter,
37         __rte_unused struct additional_para para)
38 {
39         static struct rte_flow_action_mark mark_action;
40
41         do {
42                 mark_action.id = MARK_ID;
43         } while (0);
44
45         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_MARK;
46         actions[actions_counter].conf = &mark_action;
47 }
48
49 static void
50 add_queue(struct rte_flow_action *actions,
51         uint8_t actions_counter,
52         struct additional_para para)
53 {
54         static struct rte_flow_action_queue queue_action;
55
56         do {
57                 queue_action.index = para.queue;
58         } while (0);
59
60         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_QUEUE;
61         actions[actions_counter].conf = &queue_action;
62 }
63
64 static void
65 add_jump(struct rte_flow_action *actions,
66         uint8_t actions_counter,
67         struct additional_para para)
68 {
69         static struct rte_flow_action_jump jump_action;
70
71         do {
72                 jump_action.group = para.next_table;
73         } while (0);
74
75         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_JUMP;
76         actions[actions_counter].conf = &jump_action;
77 }
78
79 static void
80 add_rss(struct rte_flow_action *actions,
81         uint8_t actions_counter,
82         struct additional_para para)
83 {
84         static struct rte_flow_action_rss *rss_action;
85         static struct action_rss_data *rss_data;
86
87         uint16_t queue;
88
89         if (rss_data == NULL)
90                 rss_data = rte_malloc("rss_data",
91                         sizeof(struct action_rss_data), 0);
92
93         if (rss_data == NULL)
94                 rte_exit(EXIT_FAILURE, "No Memory available!");
95
96         *rss_data = (struct action_rss_data){
97                 .conf = (struct rte_flow_action_rss){
98                         .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
99                         .level = 0,
100                         .types = GET_RSS_HF(),
101                         .key_len = sizeof(rss_data->key),
102                         .queue_num = para.queues_number,
103                         .key = rss_data->key,
104                         .queue = rss_data->queue,
105                 },
106                 .key = { 1 },
107                 .queue = { 0 },
108         };
109
110         for (queue = 0; queue < para.queues_number; queue++)
111                 rss_data->queue[queue] = para.queues[queue];
112
113         rss_action = &rss_data->conf;
114
115         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_RSS;
116         actions[actions_counter].conf = rss_action;
117 }
118
119 static void
120 add_set_meta(struct rte_flow_action *actions,
121         uint8_t actions_counter,
122         __rte_unused struct additional_para para)
123 {
124         static struct rte_flow_action_set_meta meta_action;
125
126         do {
127                 meta_action.data = RTE_BE32(META_DATA);
128                 meta_action.mask = RTE_BE32(0xffffffff);
129         } while (0);
130
131         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_META;
132         actions[actions_counter].conf = &meta_action;
133 }
134
135 static void
136 add_set_tag(struct rte_flow_action *actions,
137         uint8_t actions_counter,
138         __rte_unused struct additional_para para)
139 {
140         static struct rte_flow_action_set_tag tag_action;
141
142         do {
143                 tag_action.data = RTE_BE32(META_DATA);
144                 tag_action.mask = RTE_BE32(0xffffffff);
145                 tag_action.index = TAG_INDEX;
146         } while (0);
147
148         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TAG;
149         actions[actions_counter].conf = &tag_action;
150 }
151
152 static void
153 add_port_id(struct rte_flow_action *actions,
154         uint8_t actions_counter,
155         __rte_unused struct additional_para para)
156 {
157         static struct rte_flow_action_port_id port_id;
158
159         do {
160                 port_id.id = PORT_ID_DST;
161         } while (0);
162
163         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_PORT_ID;
164         actions[actions_counter].conf = &port_id;
165 }
166
167 static void
168 add_drop(struct rte_flow_action *actions,
169         uint8_t actions_counter,
170         __rte_unused struct additional_para para)
171 {
172         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DROP;
173 }
174
175 static void
176 add_count(struct rte_flow_action *actions,
177         uint8_t actions_counter,
178         __rte_unused struct additional_para para)
179 {
180         static struct rte_flow_action_count count_action;
181
182         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_COUNT;
183         actions[actions_counter].conf = &count_action;
184 }
185
186 static void
187 add_set_src_mac(struct rte_flow_action *actions,
188         uint8_t actions_counter,
189         __rte_unused struct additional_para para)
190 {
191         static struct rte_flow_action_set_mac set_mac;
192         uint32_t mac = para.counter;
193         uint16_t i;
194
195         /* Mac address to be set is random each time */
196         for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
197                 set_mac.mac_addr[i] = mac & 0xff;
198                 mac = mac >> 8;
199         }
200
201         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_MAC_SRC;
202         actions[actions_counter].conf = &set_mac;
203 }
204
205 static void
206 add_set_dst_mac(struct rte_flow_action *actions,
207         uint8_t actions_counter,
208         __rte_unused struct additional_para para)
209 {
210         static struct rte_flow_action_set_mac set_mac;
211         uint32_t mac = para.counter;
212         uint16_t i;
213
214         /* Mac address to be set is random each time */
215         for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
216                 set_mac.mac_addr[i] = mac & 0xff;
217                 mac = mac >> 8;
218         }
219
220         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_MAC_DST;
221         actions[actions_counter].conf = &set_mac;
222 }
223
224 static void
225 add_set_src_ipv4(struct rte_flow_action *actions,
226         uint8_t actions_counter,
227         __rte_unused struct additional_para para)
228 {
229         static struct rte_flow_action_set_ipv4 set_ipv4;
230
231         /* IPv4 value to be set is random each time */
232         set_ipv4.ipv4_addr = RTE_BE32(para.counter + 1);
233
234         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC;
235         actions[actions_counter].conf = &set_ipv4;
236 }
237
238 static void
239 add_set_dst_ipv4(struct rte_flow_action *actions,
240         uint8_t actions_counter,
241         __rte_unused struct additional_para para)
242 {
243         static struct rte_flow_action_set_ipv4 set_ipv4;
244
245         /* IPv4 value to be set is random each time */
246         set_ipv4.ipv4_addr = RTE_BE32(para.counter + 1);
247
248         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_DST;
249         actions[actions_counter].conf = &set_ipv4;
250 }
251
252 static void
253 add_set_src_ipv6(struct rte_flow_action *actions,
254         uint8_t actions_counter,
255         __rte_unused struct additional_para para)
256 {
257         static struct rte_flow_action_set_ipv6 set_ipv6;
258         uint32_t ipv6 = para.counter;
259         uint8_t i;
260
261         /* IPv6 value to set is random each time */
262         for (i = 0; i < 16; i++) {
263                 set_ipv6.ipv6_addr[i] = ipv6 & 0xff;
264                 ipv6 = ipv6 >> 8;
265         }
266
267         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC;
268         actions[actions_counter].conf = &set_ipv6;
269 }
270
271 static void
272 add_set_dst_ipv6(struct rte_flow_action *actions,
273         uint8_t actions_counter,
274         __rte_unused struct additional_para para)
275 {
276         static struct rte_flow_action_set_ipv6 set_ipv6;
277         uint32_t ipv6 = para.counter;
278         uint8_t i;
279
280         /* IPv6 value to set is random each time */
281         for (i = 0; i < 16; i++) {
282                 set_ipv6.ipv6_addr[i] = ipv6 & 0xff;
283                 ipv6 = ipv6 >> 8;
284         }
285
286         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_DST;
287         actions[actions_counter].conf = &set_ipv6;
288 }
289
290 static void
291 add_set_src_tp(struct rte_flow_action *actions,
292         uint8_t actions_counter,
293         __rte_unused struct additional_para para)
294 {
295         static struct rte_flow_action_set_tp set_tp;
296         uint32_t tp = para.counter;
297
298         /* TP src port is random each time */
299         if (tp > 0xffff)
300                 tp = tp >> 16;
301
302         set_tp.port = RTE_BE16(tp & 0xffff);
303
304         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TP_SRC;
305         actions[actions_counter].conf = &set_tp;
306 }
307
308 static void
309 add_set_dst_tp(struct rte_flow_action *actions,
310         uint8_t actions_counter,
311         __rte_unused struct additional_para para)
312 {
313         static struct rte_flow_action_set_tp set_tp;
314         uint32_t tp = para.counter;
315
316         /* TP src port is random each time */
317         if (tp > 0xffff)
318                 tp = tp >> 16;
319
320         set_tp.port = RTE_BE16(tp & 0xffff);
321
322         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TP_DST;
323         actions[actions_counter].conf = &set_tp;
324 }
325
326 static void
327 add_inc_tcp_ack(struct rte_flow_action *actions,
328         uint8_t actions_counter,
329         __rte_unused struct additional_para para)
330 {
331         static rte_be32_t value = RTE_BE32(1);
332
333         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_INC_TCP_ACK;
334         actions[actions_counter].conf = &value;
335 }
336
337 static void
338 add_dec_tcp_ack(struct rte_flow_action *actions,
339         uint8_t actions_counter,
340         __rte_unused struct additional_para para)
341 {
342         static rte_be32_t value = RTE_BE32(1);
343
344         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK;
345         actions[actions_counter].conf = &value;
346 }
347
348 static void
349 add_inc_tcp_seq(struct rte_flow_action *actions,
350         uint8_t actions_counter,
351         __rte_unused struct additional_para para)
352 {
353         static rte_be32_t value = RTE_BE32(1);
354
355         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ;
356         actions[actions_counter].conf = &value;
357 }
358
359 static void
360 add_dec_tcp_seq(struct rte_flow_action *actions,
361         uint8_t actions_counter,
362         __rte_unused struct additional_para para)
363 {
364         static rte_be32_t value = RTE_BE32(1);
365
366         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ;
367         actions[actions_counter].conf = &value;
368 }
369
370 static void
371 add_set_ttl(struct rte_flow_action *actions,
372         uint8_t actions_counter,
373         __rte_unused struct additional_para para)
374 {
375         static struct rte_flow_action_set_ttl set_ttl;
376         uint32_t ttl_value = para.counter;
377
378         /* Set ttl to random value each time */
379         while (ttl_value > 0xff)
380                 ttl_value = ttl_value >> 8;
381
382         set_ttl.ttl_value = ttl_value;
383
384         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TTL;
385         actions[actions_counter].conf = &set_ttl;
386 }
387
388 static void
389 add_dec_ttl(struct rte_flow_action *actions,
390         uint8_t actions_counter,
391         __rte_unused struct additional_para para)
392 {
393         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DEC_TTL;
394 }
395
396 static void
397 add_set_ipv4_dscp(struct rte_flow_action *actions,
398         uint8_t actions_counter,
399         __rte_unused struct additional_para para)
400 {
401         static struct rte_flow_action_set_dscp set_dscp;
402         uint32_t dscp_value = para.counter;
403
404         /* Set dscp to random value each time */
405         while (dscp_value > 0xff)
406                 dscp_value = dscp_value >> 8;
407
408         set_dscp.dscp = dscp_value;
409
410         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP;
411         actions[actions_counter].conf = &set_dscp;
412 }
413
414 static void
415 add_set_ipv6_dscp(struct rte_flow_action *actions,
416         uint8_t actions_counter,
417         __rte_unused struct additional_para para)
418 {
419         static struct rte_flow_action_set_dscp set_dscp;
420         uint32_t dscp_value = para.counter;
421
422         /* Set dscp to random value each time */
423         while (dscp_value > 0xff)
424                 dscp_value = dscp_value >> 8;
425
426         set_dscp.dscp = dscp_value;
427
428         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP;
429         actions[actions_counter].conf = &set_dscp;
430 }
431
432 static void
433 add_flag(struct rte_flow_action *actions,
434         uint8_t actions_counter,
435         __rte_unused struct additional_para para)
436 {
437         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_FLAG;
438 }
439
440 void
441 fill_actions(struct rte_flow_action *actions, uint64_t *flow_actions,
442         uint32_t counter, uint16_t next_table, uint16_t hairpinq)
443 {
444         struct additional_para additional_para_data;
445         uint8_t actions_counter = 0;
446         uint16_t hairpin_queues[hairpinq];
447         uint16_t queues[RXQ_NUM];
448         uint16_t i, j;
449
450         for (i = 0; i < RXQ_NUM; i++)
451                 queues[i] = i;
452
453         for (i = 0; i < hairpinq; i++)
454                 hairpin_queues[i] = i + RXQ_NUM;
455
456         additional_para_data = (struct additional_para){
457                 .queue = counter % RXQ_NUM,
458                 .next_table = next_table,
459                 .queues = queues,
460                 .queues_number = RXQ_NUM,
461                 .counter = counter,
462         };
463
464         if (hairpinq != 0) {
465                 additional_para_data.queues = hairpin_queues;
466                 additional_para_data.queues_number = hairpinq;
467                 additional_para_data.queue = (counter % hairpinq) + RXQ_NUM;
468         }
469
470         static const struct actions_dict {
471                 uint64_t mask;
472                 void (*funct)(
473                         struct rte_flow_action *actions,
474                         uint8_t actions_counter,
475                         struct additional_para para
476                         );
477         } actions_list[] = {
478                 {
479                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_MARK),
480                         .funct = add_mark,
481                 },
482                 {
483                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_COUNT),
484                         .funct = add_count,
485                 },
486                 {
487                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_META),
488                         .funct = add_set_meta,
489                 },
490                 {
491                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_TAG),
492                         .funct = add_set_tag,
493                 },
494                 {
495                         .mask = FLOW_ACTION_MASK(
496                                 RTE_FLOW_ACTION_TYPE_FLAG
497                         ),
498                         .funct = add_flag,
499                 },
500                 {
501                         .mask = FLOW_ACTION_MASK(
502                                 RTE_FLOW_ACTION_TYPE_SET_MAC_SRC
503                         ),
504                         .funct = add_set_src_mac,
505                 },
506                 {
507                         .mask = FLOW_ACTION_MASK(
508                                 RTE_FLOW_ACTION_TYPE_SET_MAC_DST
509                         ),
510                         .funct = add_set_dst_mac,
511                 },
512                 {
513                         .mask = FLOW_ACTION_MASK(
514                                 RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC
515                         ),
516                         .funct = add_set_src_ipv4,
517                 },
518                 {
519                         .mask = FLOW_ACTION_MASK(
520                                 RTE_FLOW_ACTION_TYPE_SET_IPV4_DST
521                         ),
522                         .funct = add_set_dst_ipv4,
523                 },
524                 {
525                         .mask = FLOW_ACTION_MASK(
526                                 RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC
527                         ),
528                         .funct = add_set_src_ipv6,
529                 },
530                 {
531                         .mask = FLOW_ACTION_MASK(
532                                 RTE_FLOW_ACTION_TYPE_SET_IPV6_DST
533                         ),
534                         .funct = add_set_dst_ipv6,
535                 },
536                 {
537                         .mask = FLOW_ACTION_MASK(
538                                 RTE_FLOW_ACTION_TYPE_SET_TP_SRC
539                         ),
540                         .funct = add_set_src_tp,
541                 },
542                 {
543                         .mask = FLOW_ACTION_MASK(
544                                 RTE_FLOW_ACTION_TYPE_SET_TP_DST
545                         ),
546                         .funct = add_set_dst_tp,
547                 },
548                 {
549                         .mask = FLOW_ACTION_MASK(
550                                 RTE_FLOW_ACTION_TYPE_INC_TCP_ACK
551                         ),
552                         .funct = add_inc_tcp_ack,
553                 },
554                 {
555                         .mask = FLOW_ACTION_MASK(
556                                 RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK
557                         ),
558                         .funct = add_dec_tcp_ack,
559                 },
560                 {
561                         .mask = FLOW_ACTION_MASK(
562                                 RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ
563                         ),
564                         .funct = add_inc_tcp_seq,
565                 },
566                 {
567                         .mask = FLOW_ACTION_MASK(
568                                 RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ
569                         ),
570                         .funct = add_dec_tcp_seq,
571                 },
572                 {
573                         .mask = FLOW_ACTION_MASK(
574                                 RTE_FLOW_ACTION_TYPE_SET_TTL
575                         ),
576                         .funct = add_set_ttl,
577                 },
578                 {
579                         .mask = FLOW_ACTION_MASK(
580                                 RTE_FLOW_ACTION_TYPE_DEC_TTL
581                         ),
582                         .funct = add_dec_ttl,
583                 },
584                 {
585                         .mask = FLOW_ACTION_MASK(
586                                 RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP
587                         ),
588                         .funct = add_set_ipv4_dscp,
589                 },
590                 {
591                         .mask = FLOW_ACTION_MASK(
592                                 RTE_FLOW_ACTION_TYPE_SET_IPV6_DSCP
593                         ),
594                         .funct = add_set_ipv6_dscp,
595                 },
596                 {
597                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_QUEUE),
598                         .funct = add_queue,
599                 },
600                 {
601                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_RSS),
602                         .funct = add_rss,
603                 },
604                 {
605                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_JUMP),
606                         .funct = add_jump,
607                 },
608                 {
609                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_PORT_ID),
610                         .funct = add_port_id
611                 },
612                 {
613                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_DROP),
614                         .funct = add_drop,
615                 },
616                 {
617                         .mask = HAIRPIN_QUEUE_ACTION,
618                         .funct = add_queue,
619                 },
620                 {
621                         .mask = HAIRPIN_RSS_ACTION,
622                         .funct = add_rss,
623                 },
624         };
625
626         for (j = 0; j < MAX_ACTIONS_NUM; j++) {
627                 if (flow_actions[j] == 0)
628                         break;
629                 for (i = 0; i < RTE_DIM(actions_list); i++) {
630                         if ((flow_actions[j] &
631                                 actions_list[i].mask) == 0)
632                                 continue;
633                         actions_list[i].funct(
634                                 actions, actions_counter++,
635                                 additional_para_data
636                         );
637                         break;
638                 }
639         }
640         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_END;
641 }