Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2018 Intel Corporation
3 : : */
4 : :
5 : : #include <stdalign.h>
6 : : #include <stdlib.h>
7 : : #include <string.h>
8 : :
9 : : #include <rte_common.h>
10 : : #include <rte_malloc.h>
11 : :
12 : : #include "rte_port_in_action.h"
13 : :
14 : : /**
15 : : * RTE_PORT_IN_ACTION_FLTR
16 : : */
17 : : static int
18 : : fltr_cfg_check(struct rte_port_in_action_fltr_config *cfg)
19 : : {
20 [ # # ]: 0 : if (cfg == NULL)
21 : : return -1;
22 : :
23 : : return 0;
24 : : }
25 : :
26 : : struct fltr_data {
27 : : uint32_t port_id;
28 : : };
29 : :
30 : : static void
31 : : fltr_init(struct fltr_data *data,
32 : : struct rte_port_in_action_fltr_config *cfg)
33 : : {
34 : 0 : data->port_id = cfg->port_id;
35 : 0 : }
36 : :
37 : : static int
38 : : fltr_apply(struct fltr_data *data,
39 : : struct rte_port_in_action_fltr_params *p)
40 : : {
41 : : /* Check input arguments */
42 : : if (p == NULL)
43 : : return -1;
44 : :
45 : 0 : data->port_id = p->port_id;
46 : :
47 : : return 0;
48 : : }
49 : :
50 : : /**
51 : : * RTE_PORT_IN_ACTION_LB
52 : : */
53 : : static int
54 : : lb_cfg_check(struct rte_port_in_action_lb_config *cfg)
55 : : {
56 [ # # ]: 0 : if ((cfg == NULL) ||
57 [ # # # # ]: 0 : (cfg->key_size < RTE_PORT_IN_ACTION_LB_KEY_SIZE_MIN) ||
58 : : (cfg->key_size > RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX) ||
59 : 0 : (!rte_is_power_of_2(cfg->key_size)) ||
60 [ # # ]: 0 : (cfg->f_hash == NULL))
61 : : return -1;
62 : :
63 : : return 0;
64 : : }
65 : :
66 : : struct lb_data {
67 : : uint32_t port_id[RTE_PORT_IN_ACTION_LB_TABLE_SIZE];
68 : : };
69 : :
70 : : static void
71 : : lb_init(struct lb_data *data,
72 : : struct rte_port_in_action_lb_config *cfg)
73 : : {
74 : 0 : memcpy(data->port_id, cfg->port_id, sizeof(cfg->port_id));
75 : 0 : }
76 : :
77 : : static int
78 : : lb_apply(struct lb_data *data,
79 : : struct rte_port_in_action_lb_params *p)
80 : : {
81 : : /* Check input arguments */
82 : : if (p == NULL)
83 : : return -1;
84 : :
85 : 0 : memcpy(data->port_id, p->port_id, sizeof(p->port_id));
86 : :
87 : : return 0;
88 : : }
89 : :
90 : : /**
91 : : * Action profile
92 : : */
93 : : static int
94 : : action_valid(enum rte_port_in_action_type action)
95 : : {
96 [ # # # # ]: 0 : switch (action) {
97 : : case RTE_PORT_IN_ACTION_FLTR:
98 : : case RTE_PORT_IN_ACTION_LB:
99 : : return 1;
100 : : default:
101 : : return 0;
102 : : }
103 : : }
104 : :
105 : : #define RTE_PORT_IN_ACTION_MAX 64
106 : :
107 : : struct ap_config {
108 : : uint64_t action_mask;
109 : : struct rte_port_in_action_fltr_config fltr;
110 : : struct rte_port_in_action_lb_config lb;
111 : : };
112 : :
113 : : static size_t
114 : : action_cfg_size(enum rte_port_in_action_type action)
115 : : {
116 [ # # ]: 0 : switch (action) {
117 : : case RTE_PORT_IN_ACTION_FLTR:
118 : : return sizeof(struct rte_port_in_action_fltr_config);
119 : 0 : case RTE_PORT_IN_ACTION_LB:
120 : 0 : return sizeof(struct rte_port_in_action_lb_config);
121 : : default:
122 : : return 0;
123 : : }
124 : : }
125 : :
126 : : static void*
127 : : action_cfg_get(struct ap_config *ap_config,
128 : : enum rte_port_in_action_type type)
129 : : {
130 : 0 : switch (type) {
131 : 0 : case RTE_PORT_IN_ACTION_FLTR:
132 : 0 : return &ap_config->fltr;
133 : :
134 : 0 : case RTE_PORT_IN_ACTION_LB:
135 : 0 : return &ap_config->lb;
136 : :
137 : : default:
138 : : return NULL;
139 : : }
140 : : }
141 : :
142 : : static void
143 [ # # # ]: 0 : action_cfg_set(struct ap_config *ap_config,
144 : : enum rte_port_in_action_type type,
145 : : void *action_cfg)
146 : : {
147 : : void *dst = action_cfg_get(ap_config, type);
148 : :
149 : : if (dst)
150 : : memcpy(dst, action_cfg, action_cfg_size(type));
151 : :
152 : 0 : ap_config->action_mask |= 1LLU << type;
153 : 0 : }
154 : :
155 : : struct ap_data {
156 : : size_t offset[RTE_PORT_IN_ACTION_MAX];
157 : : size_t total_size;
158 : : };
159 : :
160 : : static size_t
161 : : action_data_size(enum rte_port_in_action_type action,
162 : : struct ap_config *ap_config __rte_unused)
163 : : {
164 : 0 : switch (action) {
165 : : case RTE_PORT_IN_ACTION_FLTR:
166 : : return sizeof(struct fltr_data);
167 : :
168 : 0 : case RTE_PORT_IN_ACTION_LB:
169 : 0 : return sizeof(struct lb_data);
170 : :
171 : 0 : default:
172 : 0 : return 0;
173 : : }
174 : : }
175 : :
176 : : static void
177 : 0 : action_data_offset_set(struct ap_data *ap_data,
178 : : struct ap_config *ap_config)
179 : : {
180 : 0 : uint64_t action_mask = ap_config->action_mask;
181 : : size_t offset;
182 : : uint32_t action;
183 : :
184 : 0 : memset(ap_data->offset, 0, sizeof(ap_data->offset));
185 : :
186 : : offset = 0;
187 [ # # ]: 0 : for (action = 0; action < RTE_PORT_IN_ACTION_MAX; action++)
188 [ # # ]: 0 : if (action_mask & (1LLU << action)) {
189 [ # # # ]: 0 : ap_data->offset[action] = offset;
190 : 0 : offset += action_data_size((enum rte_port_in_action_type)action,
191 : : ap_config);
192 : : }
193 : :
194 : 0 : ap_data->total_size = offset;
195 : 0 : }
196 : :
197 : : struct rte_port_in_action_profile {
198 : : struct ap_config cfg;
199 : : struct ap_data data;
200 : : int frozen;
201 : : };
202 : :
203 : : struct rte_port_in_action_profile *
204 : 0 : rte_port_in_action_profile_create(uint32_t socket_id)
205 : : {
206 : : struct rte_port_in_action_profile *ap;
207 : :
208 : : /* Memory allocation */
209 : 0 : ap = rte_zmalloc_socket(NULL,
210 : : sizeof(struct rte_port_in_action_profile),
211 : : RTE_CACHE_LINE_SIZE,
212 : : socket_id);
213 [ # # ]: 0 : if (ap == NULL)
214 : 0 : return NULL;
215 : :
216 : : return ap;
217 : : }
218 : :
219 : : int
220 : 0 : rte_port_in_action_profile_action_register(struct rte_port_in_action_profile *profile,
221 : : enum rte_port_in_action_type type,
222 : : void *action_config)
223 : : {
224 : : int status;
225 : :
226 : : /* Check input arguments */
227 [ # # ]: 0 : if ((profile == NULL) ||
228 [ # # ]: 0 : profile->frozen ||
229 : 0 : (action_valid(type) == 0) ||
230 [ # # ]: 0 : (profile->cfg.action_mask & (1LLU << type)) ||
231 : : ((action_cfg_size(type) == 0) && action_config) ||
232 [ # # ]: 0 : (action_cfg_size(type) && (action_config == NULL)))
233 : : return -EINVAL;
234 : :
235 [ # # ]: 0 : switch (type) {
236 : : case RTE_PORT_IN_ACTION_FLTR:
237 : : status = fltr_cfg_check(action_config);
238 : : break;
239 : :
240 : : case RTE_PORT_IN_ACTION_LB:
241 : : status = lb_cfg_check(action_config);
242 : : break;
243 : :
244 : : default:
245 : : status = 0;
246 : : break;
247 : : }
248 : :
249 : : if (status)
250 : : return status;
251 : :
252 : : /* Action enable */
253 : 0 : action_cfg_set(&profile->cfg, type, action_config);
254 : :
255 : 0 : return 0;
256 : : }
257 : :
258 : : int
259 : 0 : rte_port_in_action_profile_freeze(struct rte_port_in_action_profile *profile)
260 : : {
261 [ # # ]: 0 : if (profile->frozen)
262 : : return -EBUSY;
263 : :
264 : 0 : action_data_offset_set(&profile->data, &profile->cfg);
265 : 0 : profile->frozen = 1;
266 : :
267 : 0 : return 0;
268 : : }
269 : :
270 : : int
271 : 0 : rte_port_in_action_profile_free(struct rte_port_in_action_profile *profile)
272 : : {
273 [ # # ]: 0 : if (profile == NULL)
274 : : return 0;
275 : :
276 : 0 : free(profile);
277 : 0 : return 0;
278 : : }
279 : :
280 : : /**
281 : : * Action
282 : : */
283 : : struct rte_port_in_action {
284 : : struct ap_config cfg;
285 : : struct ap_data data;
286 : : alignas(RTE_CACHE_LINE_SIZE) uint8_t memory[0];
287 : : };
288 : :
289 : : static __rte_always_inline void *
290 : : action_data_get(struct rte_port_in_action *action,
291 : : enum rte_port_in_action_type type)
292 : : {
293 : 0 : size_t offset = action->data.offset[type];
294 : :
295 : 0 : return &action->memory[offset];
296 : : }
297 : :
298 : : static void
299 : 0 : action_data_init(struct rte_port_in_action *action,
300 : : enum rte_port_in_action_type type)
301 : : {
302 : : void *data = action_data_get(action, type);
303 : :
304 [ # # # ]: 0 : switch (type) {
305 : 0 : case RTE_PORT_IN_ACTION_FLTR:
306 : : fltr_init(data, &action->cfg.fltr);
307 : : return;
308 : :
309 : 0 : case RTE_PORT_IN_ACTION_LB:
310 : : lb_init(data, &action->cfg.lb);
311 : : return;
312 : :
313 : : default:
314 : : return;
315 : : }
316 : : }
317 : :
318 : : struct rte_port_in_action *
319 : 0 : rte_port_in_action_create(struct rte_port_in_action_profile *profile,
320 : : uint32_t socket_id)
321 : : {
322 : : struct rte_port_in_action *action;
323 : : size_t size;
324 : : uint32_t i;
325 : :
326 : : /* Check input arguments */
327 [ # # ]: 0 : if ((profile == NULL) ||
328 [ # # ]: 0 : (profile->frozen == 0))
329 : : return NULL;
330 : :
331 : : /* Memory allocation */
332 : 0 : size = sizeof(struct rte_port_in_action) + profile->data.total_size;
333 : 0 : size = RTE_CACHE_LINE_ROUNDUP(size);
334 : :
335 : 0 : action = rte_zmalloc_socket(NULL,
336 : : size,
337 : : RTE_CACHE_LINE_SIZE,
338 : : socket_id);
339 [ # # ]: 0 : if (action == NULL)
340 : : return NULL;
341 : :
342 : : /* Initialization */
343 : 0 : memcpy(&action->cfg, &profile->cfg, sizeof(profile->cfg));
344 : 0 : memcpy(&action->data, &profile->data, sizeof(profile->data));
345 : :
346 [ # # ]: 0 : for (i = 0; i < RTE_PORT_IN_ACTION_MAX; i++)
347 [ # # ]: 0 : if (action->cfg.action_mask & (1LLU << i))
348 : 0 : action_data_init(action,
349 : : (enum rte_port_in_action_type)i);
350 : :
351 : : return action;
352 : : }
353 : :
354 : : int
355 : 0 : rte_port_in_action_apply(struct rte_port_in_action *action,
356 : : enum rte_port_in_action_type type,
357 : : void *action_params)
358 : : {
359 : : void *action_data;
360 : :
361 : : /* Check input arguments */
362 [ # # ]: 0 : if ((action == NULL) ||
363 : 0 : (action_valid(type) == 0) ||
364 [ # # # # ]: 0 : ((action->cfg.action_mask & (1LLU << type)) == 0) ||
365 : : (action_params == NULL))
366 : : return -EINVAL;
367 : :
368 : : /* Data update */
369 : : action_data = action_data_get(action, type);
370 : :
371 [ # # ]: 0 : switch (type) {
372 : : case RTE_PORT_IN_ACTION_FLTR:
373 : 0 : return fltr_apply(action_data,
374 : : action_params);
375 : :
376 : : case RTE_PORT_IN_ACTION_LB:
377 : 0 : return lb_apply(action_data,
378 : : action_params);
379 : :
380 : : default:
381 : : return -EINVAL;
382 : : }
383 : : }
384 : :
385 : : static int
386 : 0 : ah_filter_on_match(struct rte_pipeline *p,
387 : : struct rte_mbuf **pkts,
388 : : uint32_t n_pkts,
389 : : void *arg)
390 : : {
391 : : struct rte_port_in_action *action = arg;
392 : : struct rte_port_in_action_fltr_config *cfg = &action->cfg.fltr;
393 : : uint64_t *key_mask = (uint64_t *) cfg->key_mask;
394 : : uint64_t *key = (uint64_t *) cfg->key;
395 : 0 : uint32_t key_offset = cfg->key_offset;
396 : : struct fltr_data *data = action_data_get(action,
397 : : RTE_PORT_IN_ACTION_FLTR);
398 : : uint32_t i;
399 : :
400 [ # # ]: 0 : for (i = 0; i < n_pkts; i++) {
401 : 0 : struct rte_mbuf *pkt = pkts[i];
402 : 0 : uint64_t *pkt_key = RTE_MBUF_METADATA_UINT64_PTR(pkt,
403 : : key_offset);
404 : :
405 : 0 : uint64_t xor0 = (pkt_key[0] & key_mask[0]) ^ key[0];
406 : 0 : uint64_t xor1 = (pkt_key[1] & key_mask[1]) ^ key[1];
407 : 0 : uint64_t or = xor0 | xor1;
408 : :
409 [ # # ]: 0 : if (or == 0) {
410 : 0 : rte_pipeline_ah_packet_hijack(p, 1LLU << i);
411 : 0 : rte_pipeline_port_out_packet_insert(p,
412 : : data->port_id, pkt);
413 : : }
414 : : }
415 : :
416 : 0 : return 0;
417 : : }
418 : :
419 : : static int
420 : 0 : ah_filter_on_mismatch(struct rte_pipeline *p,
421 : : struct rte_mbuf **pkts,
422 : : uint32_t n_pkts,
423 : : void *arg)
424 : : {
425 : : struct rte_port_in_action *action = arg;
426 : : struct rte_port_in_action_fltr_config *cfg = &action->cfg.fltr;
427 : : uint64_t *key_mask = (uint64_t *) cfg->key_mask;
428 : : uint64_t *key = (uint64_t *) cfg->key;
429 : 0 : uint32_t key_offset = cfg->key_offset;
430 : : struct fltr_data *data = action_data_get(action,
431 : : RTE_PORT_IN_ACTION_FLTR);
432 : : uint32_t i;
433 : :
434 [ # # ]: 0 : for (i = 0; i < n_pkts; i++) {
435 : 0 : struct rte_mbuf *pkt = pkts[i];
436 : 0 : uint64_t *pkt_key = RTE_MBUF_METADATA_UINT64_PTR(pkt,
437 : : key_offset);
438 : :
439 : 0 : uint64_t xor0 = (pkt_key[0] & key_mask[0]) ^ key[0];
440 : 0 : uint64_t xor1 = (pkt_key[1] & key_mask[1]) ^ key[1];
441 : 0 : uint64_t or = xor0 | xor1;
442 : :
443 [ # # ]: 0 : if (or) {
444 : 0 : rte_pipeline_ah_packet_hijack(p, 1LLU << i);
445 : 0 : rte_pipeline_port_out_packet_insert(p,
446 : : data->port_id, pkt);
447 : : }
448 : : }
449 : :
450 : 0 : return 0;
451 : : }
452 : :
453 : : static int
454 : 0 : ah_lb(struct rte_pipeline *p,
455 : : struct rte_mbuf **pkts,
456 : : uint32_t n_pkts,
457 : : void *arg)
458 : : {
459 : : struct rte_port_in_action *action = arg;
460 : : struct rte_port_in_action_lb_config *cfg = &action->cfg.lb;
461 : : struct lb_data *data = action_data_get(action, RTE_PORT_IN_ACTION_LB);
462 : 0 : uint64_t pkt_mask = RTE_LEN2MASK(n_pkts, uint64_t);
463 : : uint32_t i;
464 : :
465 : 0 : rte_pipeline_ah_packet_hijack(p, pkt_mask);
466 : :
467 [ # # ]: 0 : for (i = 0; i < n_pkts; i++) {
468 : 0 : struct rte_mbuf *pkt = pkts[i];
469 : 0 : uint8_t *pkt_key = RTE_MBUF_METADATA_UINT8_PTR(pkt,
470 : : cfg->key_offset);
471 : :
472 : 0 : uint64_t digest = cfg->f_hash(pkt_key,
473 : 0 : cfg->key_mask,
474 : : cfg->key_size,
475 : : cfg->seed);
476 : 0 : uint64_t pos = digest & (RTE_PORT_IN_ACTION_LB_TABLE_SIZE - 1);
477 : 0 : uint32_t port_id = data->port_id[pos];
478 : :
479 : 0 : rte_pipeline_port_out_packet_insert(p, port_id, pkt);
480 : : }
481 : :
482 : 0 : return 0;
483 : : }
484 : :
485 : : static rte_pipeline_port_in_action_handler
486 : : ah_selector(struct rte_port_in_action *action)
487 : : {
488 [ # # ]: 0 : if (action->cfg.action_mask == 0)
489 : : return NULL;
490 : :
491 [ # # ]: 0 : if (action->cfg.action_mask == 1LLU << RTE_PORT_IN_ACTION_FLTR)
492 : 0 : return (action->cfg.fltr.filter_on_match) ?
493 [ # # ]: 0 : ah_filter_on_match : ah_filter_on_mismatch;
494 : :
495 [ # # ]: 0 : if (action->cfg.action_mask == 1LLU << RTE_PORT_IN_ACTION_LB)
496 : : return ah_lb;
497 : :
498 : : return NULL;
499 : : }
500 : :
501 : : int
502 : 0 : rte_port_in_action_params_get(struct rte_port_in_action *action,
503 : : struct rte_pipeline_port_in_params *params)
504 : : {
505 : : rte_pipeline_port_in_action_handler f_action;
506 : :
507 : : /* Check input arguments */
508 : 0 : if ((action == NULL) ||
509 [ # # ]: 0 : (params == NULL))
510 : : return -EINVAL;
511 : :
512 : : f_action = ah_selector(action);
513 : :
514 : : /* Fill in params */
515 : 0 : params->f_action = f_action;
516 : 0 : params->arg_ah = (f_action) ? action : NULL;
517 : :
518 : 0 : return 0;
519 : : }
520 : :
521 : : int
522 : 0 : rte_port_in_action_free(struct rte_port_in_action *action)
523 : : {
524 [ # # ]: 0 : if (action == NULL)
525 : : return 0;
526 : :
527 : 0 : rte_free(action);
528 : :
529 : 0 : return 0;
530 : : }
|