pipeline: add table action APIs
[dpdk.git] / lib / librte_pipeline / rte_table_action.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include <rte_malloc.h>
9
10 #include <rte_common.h>
11 #include <rte_malloc.h>
12
13 #include "rte_table_action.h"
14
15 /**
16  * RTE_TABLE_ACTION_FWD
17  */
18 #define fwd_data rte_pipeline_table_entry
19
20 static int
21 fwd_apply(struct fwd_data *data,
22         struct rte_table_action_fwd_params *p)
23 {
24         data->action = p->action;
25
26         if (p->action == RTE_PIPELINE_ACTION_PORT)
27                 data->port_id = p->id;
28
29         if (p->action == RTE_PIPELINE_ACTION_TABLE)
30                 data->table_id = p->id;
31
32         return 0;
33 }
34
35 /**
36  * Action profile
37  */
38 static int
39 action_valid(enum rte_table_action_type action)
40 {
41         switch (action) {
42         case RTE_TABLE_ACTION_FWD:
43                 return 1;
44         default:
45                 return 0;
46         }
47 }
48
49
50 #define RTE_TABLE_ACTION_MAX                      64
51
52 struct ap_config {
53         uint64_t action_mask;
54         struct rte_table_action_common_config common;
55 };
56
57 static size_t
58 action_cfg_size(enum rte_table_action_type action)
59 {
60         switch (action) {
61         default:
62                 return 0;
63         }
64 }
65
66 static void*
67 action_cfg_get(struct ap_config *ap_config __rte_unused,
68         enum rte_table_action_type type)
69 {
70         switch (type) {
71         default:
72                 return NULL;
73         }
74 }
75
76 static void
77 action_cfg_set(struct ap_config *ap_config,
78         enum rte_table_action_type type,
79         void *action_cfg)
80 {
81         void *dst = action_cfg_get(ap_config, type);
82
83         if (dst)
84                 memcpy(dst, action_cfg, action_cfg_size(type));
85
86         ap_config->action_mask |= 1LLU << type;
87 }
88
89 struct ap_data {
90         size_t offset[RTE_TABLE_ACTION_MAX];
91         size_t total_size;
92 };
93
94 static size_t
95 action_data_size(enum rte_table_action_type action,
96         struct ap_config *ap_config __rte_unused)
97 {
98         switch (action) {
99         case RTE_TABLE_ACTION_FWD:
100                 return sizeof(struct fwd_data);
101
102         default:
103                 return 0;
104         }
105 }
106
107
108 static void
109 action_data_offset_set(struct ap_data *ap_data,
110         struct ap_config *ap_config)
111 {
112         uint64_t action_mask = ap_config->action_mask;
113         size_t offset;
114         uint32_t action;
115
116         memset(ap_data->offset, 0, sizeof(ap_data->offset));
117
118         offset = 0;
119         for (action = 0; action < RTE_TABLE_ACTION_MAX; action++)
120                 if (action_mask & (1LLU << action)) {
121                         ap_data->offset[action] = offset;
122                         offset += action_data_size((enum rte_table_action_type)action,
123                                 ap_config);
124                 }
125
126         ap_data->total_size = offset;
127 }
128
129 struct rte_table_action_profile {
130         struct ap_config cfg;
131         struct ap_data data;
132         int frozen;
133 };
134
135 struct rte_table_action_profile *
136 rte_table_action_profile_create(struct rte_table_action_common_config *common)
137 {
138         struct rte_table_action_profile *ap;
139
140         /* Check input arguments */
141         if (common == NULL)
142                 return NULL;
143
144         /* Memory allocation */
145         ap = calloc(1, sizeof(struct rte_table_action_profile));
146         if (ap == NULL)
147                 return NULL;
148
149         /* Initialization */
150         memcpy(&ap->cfg.common, common, sizeof(*common));
151
152         return ap;
153 }
154
155
156 int
157 rte_table_action_profile_action_register(struct rte_table_action_profile *profile,
158         enum rte_table_action_type type,
159         void *action_config)
160 {
161         /* Check input arguments */
162         if ((profile == NULL) ||
163                 profile->frozen ||
164                 (action_valid(type) == 0) ||
165                 (profile->cfg.action_mask & (1LLU << type)) ||
166                 ((action_cfg_size(type) == 0) && action_config) ||
167                 (action_cfg_size(type) && (action_config == NULL)))
168                 return -EINVAL;
169
170         /* Action enable */
171         action_cfg_set(&profile->cfg, type, action_config);
172
173         return 0;
174 }
175
176 int
177 rte_table_action_profile_freeze(struct rte_table_action_profile *profile)
178 {
179         if (profile->frozen)
180                 return -EBUSY;
181
182         profile->cfg.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
183         action_data_offset_set(&profile->data, &profile->cfg);
184         profile->frozen = 1;
185
186         return 0;
187 }
188
189 int
190 rte_table_action_profile_free(struct rte_table_action_profile *profile)
191 {
192         if (profile == NULL)
193                 return 0;
194
195         free(profile);
196         return 0;
197 }
198
199 struct rte_table_action {
200         struct ap_config cfg;
201         struct ap_data data;
202 };
203
204 struct rte_table_action *
205 rte_table_action_create(struct rte_table_action_profile *profile,
206         uint32_t socket_id)
207 {
208         struct rte_table_action *action;
209
210         /* Check input arguments */
211         if ((profile == NULL) ||
212                 (profile->frozen == 0))
213                 return NULL;
214
215         /* Memory allocation */
216         action = rte_zmalloc_socket(NULL,
217                 sizeof(struct rte_table_action),
218                 RTE_CACHE_LINE_SIZE,
219                 socket_id);
220         if (action == NULL)
221                 return NULL;
222
223         /* Initialization */
224         memcpy(&action->cfg, &profile->cfg, sizeof(profile->cfg));
225         memcpy(&action->data, &profile->data, sizeof(profile->data));
226
227         return action;
228 }
229
230 static __rte_always_inline void *
231 action_data_get(void *data,
232         struct rte_table_action *action,
233         enum rte_table_action_type type)
234 {
235         size_t offset = action->data.offset[type];
236         uint8_t *data_bytes = data;
237
238         return &data_bytes[offset];
239 }
240
241 int
242 rte_table_action_apply(struct rte_table_action *action,
243         void *data,
244         enum rte_table_action_type type,
245         void *action_params)
246 {
247         void *action_data;
248
249         /* Check input arguments */
250         if ((action == NULL) ||
251                 (data == NULL) ||
252                 (action_valid(type) == 0) ||
253                 ((action->cfg.action_mask & (1LLU << type)) == 0) ||
254                 (action_params == NULL))
255                 return -EINVAL;
256
257         /* Data update */
258         action_data = action_data_get(data, action, type);
259
260         switch (type) {
261         case RTE_TABLE_ACTION_FWD:
262                 return fwd_apply(action_data,
263                         action_params);
264
265         default:
266                 return -EINVAL;
267         }
268 }
269
270 int
271 rte_table_action_free(struct rte_table_action *action)
272 {
273         if (action == NULL)
274                 return 0;
275
276         rte_free(action);
277
278         return 0;
279 }