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