d115cdd72307c2cda1ddffd346e5d62973fb33c0
[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 };
25
26 /* Storage for struct rte_flow_action_rss including external data. */
27 struct action_rss_data {
28         struct rte_flow_action_rss conf;
29         uint8_t key[40];
30         uint16_t queue[128];
31 };
32
33 static void
34 add_mark(struct rte_flow_action *actions,
35         uint8_t actions_counter,
36         __rte_unused struct additional_para para)
37 {
38         static struct rte_flow_action_mark mark_action;
39
40         do {
41                 mark_action.id = MARK_ID;
42         } while (0);
43
44         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_MARK;
45         actions[actions_counter].conf = &mark_action;
46 }
47
48 static void
49 add_queue(struct rte_flow_action *actions,
50         uint8_t actions_counter,
51         struct additional_para para)
52 {
53         static struct rte_flow_action_queue queue_action;
54
55         do {
56                 queue_action.index = para.queue;
57         } while (0);
58
59         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_QUEUE;
60         actions[actions_counter].conf = &queue_action;
61 }
62
63 static void
64 add_jump(struct rte_flow_action *actions,
65         uint8_t actions_counter,
66         struct additional_para para)
67 {
68         static struct rte_flow_action_jump jump_action;
69
70         do {
71                 jump_action.group = para.next_table;
72         } while (0);
73
74         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_JUMP;
75         actions[actions_counter].conf = &jump_action;
76 }
77
78 static void
79 add_rss(struct rte_flow_action *actions,
80         uint8_t actions_counter,
81         struct additional_para para)
82 {
83         static struct rte_flow_action_rss *rss_action;
84         static struct action_rss_data *rss_data;
85
86         uint16_t queue;
87
88         rss_data = rte_malloc("rss_data",
89                 sizeof(struct action_rss_data), 0);
90
91         if (rss_data == NULL)
92                 rte_exit(EXIT_FAILURE, "No Memory available!");
93
94         *rss_data = (struct action_rss_data){
95                 .conf = (struct rte_flow_action_rss){
96                         .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
97                         .level = 0,
98                         .types = GET_RSS_HF(),
99                         .key_len = sizeof(rss_data->key),
100                         .queue_num = para.queues_number,
101                         .key = rss_data->key,
102                         .queue = rss_data->queue,
103                 },
104                 .key = { 1 },
105                 .queue = { 0 },
106         };
107
108         for (queue = 0; queue < para.queues_number; queue++)
109                 rss_data->queue[queue] = para.queues[queue];
110
111         rss_action = &rss_data->conf;
112
113         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_RSS;
114         actions[actions_counter].conf = rss_action;
115 }
116
117 static void
118 add_set_meta(struct rte_flow_action *actions,
119         uint8_t actions_counter,
120         __rte_unused struct additional_para para)
121 {
122         static struct rte_flow_action_set_meta meta_action;
123
124         do {
125                 meta_action.data = RTE_BE32(META_DATA);
126                 meta_action.mask = RTE_BE32(0xffffffff);
127         } while (0);
128
129         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_META;
130         actions[actions_counter].conf = &meta_action;
131 }
132
133 static void
134 add_set_tag(struct rte_flow_action *actions,
135         uint8_t actions_counter,
136         __rte_unused struct additional_para para)
137 {
138         static struct rte_flow_action_set_tag tag_action;
139
140         do {
141                 tag_action.data = RTE_BE32(META_DATA);
142                 tag_action.mask = RTE_BE32(0xffffffff);
143                 tag_action.index = TAG_INDEX;
144         } while (0);
145
146         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_SET_TAG;
147         actions[actions_counter].conf = &tag_action;
148 }
149
150 static void
151 add_port_id(struct rte_flow_action *actions,
152         uint8_t actions_counter,
153         __rte_unused struct additional_para para)
154 {
155         static struct rte_flow_action_port_id port_id;
156
157         do {
158                 port_id.id = PORT_ID_DST;
159         } while (0);
160
161         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_PORT_ID;
162         actions[actions_counter].conf = &port_id;
163 }
164
165 static void
166 add_drop(struct rte_flow_action *actions,
167         uint8_t actions_counter,
168         __rte_unused struct additional_para para)
169 {
170         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_DROP;
171 }
172
173 static void
174 add_count(struct rte_flow_action *actions,
175         uint8_t actions_counter,
176         __rte_unused struct additional_para para)
177 {
178         static struct rte_flow_action_count count_action;
179
180         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_COUNT;
181         actions[actions_counter].conf = &count_action;
182 }
183
184 void
185 fill_actions(struct rte_flow_action *actions, uint64_t *flow_actions,
186         uint32_t counter, uint16_t next_table, uint16_t hairpinq)
187 {
188         struct additional_para additional_para_data;
189         uint8_t actions_counter = 0;
190         uint16_t hairpin_queues[hairpinq];
191         uint16_t queues[RXQ_NUM];
192         uint16_t i, j;
193
194         for (i = 0; i < RXQ_NUM; i++)
195                 queues[i] = i;
196
197         for (i = 0; i < hairpinq; i++)
198                 hairpin_queues[i] = i + RXQ_NUM;
199
200         additional_para_data = (struct additional_para){
201                 .queue = counter % RXQ_NUM,
202                 .next_table = next_table,
203                 .queues = queues,
204                 .queues_number = RXQ_NUM,
205         };
206
207         if (hairpinq != 0) {
208                 additional_para_data.queues = hairpin_queues;
209                 additional_para_data.queues_number = hairpinq;
210                 additional_para_data.queue = (counter % hairpinq) + RXQ_NUM;
211         }
212
213         static const struct actions_dict {
214                 uint64_t mask;
215                 void (*funct)(
216                         struct rte_flow_action *actions,
217                         uint8_t actions_counter,
218                         struct additional_para para
219                         );
220         } actions_list[] = {
221                 {
222                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_MARK),
223                         .funct = add_mark,
224                 },
225                 {
226                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_COUNT),
227                         .funct = add_count,
228                 },
229                 {
230                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_META),
231                         .funct = add_set_meta,
232                 },
233                 {
234                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_SET_TAG),
235                         .funct = add_set_tag,
236                 },
237                 {
238                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_QUEUE),
239                         .funct = add_queue,
240                 },
241                 {
242                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_RSS),
243                         .funct = add_rss,
244                 },
245                 {
246                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_JUMP),
247                         .funct = add_jump,
248                 },
249                 {
250                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_PORT_ID),
251                         .funct = add_port_id
252                 },
253                 {
254                         .mask = FLOW_ACTION_MASK(RTE_FLOW_ACTION_TYPE_DROP),
255                         .funct = add_drop,
256                 },
257                 {
258                         .mask = HAIRPIN_QUEUE_ACTION,
259                         .funct = add_queue,
260                 },
261                 {
262                         .mask = HAIRPIN_RSS_ACTION,
263                         .funct = add_rss,
264                 },
265         };
266
267         for (j = 0; j < MAX_ACTIONS_NUM; j++) {
268                 if (flow_actions[j] == 0)
269                         break;
270                 for (i = 0; i < RTE_DIM(actions_list); i++) {
271                         if ((flow_actions[j] &
272                                 actions_list[i].mask) == 0)
273                                 continue;
274                         actions_list[i].funct(
275                                 actions, actions_counter++,
276                                 additional_para_data
277                         );
278                         break;
279                 }
280         }
281         actions[actions_counter].type = RTE_FLOW_ACTION_TYPE_END;
282 }