]> git.proxmox.com Git - ceph.git/blame - ceph/src/dpdk/examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / dpdk / examples / ip_pipeline / pipeline / pipeline_flow_actions_be.c
CommitLineData
7c673cae
FG
1/*-
2 * BSD LICENSE
3 *
4 * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <string.h>
35
36#include <rte_common.h>
37#include <rte_malloc.h>
38#include <rte_cycles.h>
39#include <rte_table_array.h>
40#include <rte_byteorder.h>
41#include <rte_ip.h>
42
43#include "pipeline_actions_common.h"
44#include "pipeline_flow_actions_be.h"
45#include "parser.h"
46#include "hash_func.h"
47
48int
49pipeline_fa_flow_params_set_default(struct pipeline_fa_flow_params *params)
50{
51 uint32_t i;
52
53 if (params == NULL)
54 return -1;
55
56 for (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) {
57 struct rte_meter_trtcm_params *m = &params->m[i];
58
59 m->cir = 1;
60 m->cbs = 1;
61 m->pir = 1;
62 m->pbs = 2;
63 }
64
65 for (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) {
66 struct pipeline_fa_policer_params *p = &params->p[i];
67 uint32_t j;
68
69 for (j = 0; j < e_RTE_METER_COLORS; j++) {
70 struct pipeline_fa_policer_action *a = &p->action[j];
71
72 a->drop = 0;
73 a->color = (enum rte_meter_color) j;
74 }
75 }
76
77 params->port_id = 0;
78
79 return 0;
80}
81
82struct dscp_entry {
83 uint32_t traffic_class;
84 enum rte_meter_color color;
85};
86
87struct pipeline_flow_actions {
88 struct pipeline p;
89 struct pipeline_fa_params params;
90 pipeline_msg_req_handler custom_handlers[PIPELINE_FA_MSG_REQS];
91
92 struct dscp_entry dscp[PIPELINE_FA_N_DSCP];
93} __rte_cache_aligned;
94
95static void *
96pipeline_fa_msg_req_custom_handler(struct pipeline *p, void *msg);
97
98static pipeline_msg_req_handler handlers[] = {
99 [PIPELINE_MSG_REQ_PING] =
100 pipeline_msg_req_ping_handler,
101 [PIPELINE_MSG_REQ_STATS_PORT_IN] =
102 pipeline_msg_req_stats_port_in_handler,
103 [PIPELINE_MSG_REQ_STATS_PORT_OUT] =
104 pipeline_msg_req_stats_port_out_handler,
105 [PIPELINE_MSG_REQ_STATS_TABLE] =
106 pipeline_msg_req_stats_table_handler,
107 [PIPELINE_MSG_REQ_PORT_IN_ENABLE] =
108 pipeline_msg_req_port_in_enable_handler,
109 [PIPELINE_MSG_REQ_PORT_IN_DISABLE] =
110 pipeline_msg_req_port_in_disable_handler,
111 [PIPELINE_MSG_REQ_CUSTOM] =
112 pipeline_fa_msg_req_custom_handler,
113};
114
115static void *
116pipeline_fa_msg_req_flow_config_handler(struct pipeline *p, void *msg);
117
118static void *
119pipeline_fa_msg_req_flow_config_bulk_handler(struct pipeline *p, void *msg);
120
121static void *
122pipeline_fa_msg_req_dscp_config_handler(struct pipeline *p, void *msg);
123
124static void *
125pipeline_fa_msg_req_policer_stats_read_handler(struct pipeline *p, void *msg);
126
127static pipeline_msg_req_handler custom_handlers[] = {
128 [PIPELINE_FA_MSG_REQ_FLOW_CONFIG] =
129 pipeline_fa_msg_req_flow_config_handler,
130 [PIPELINE_FA_MSG_REQ_FLOW_CONFIG_BULK] =
131 pipeline_fa_msg_req_flow_config_bulk_handler,
132 [PIPELINE_FA_MSG_REQ_DSCP_CONFIG] =
133 pipeline_fa_msg_req_dscp_config_handler,
134 [PIPELINE_FA_MSG_REQ_POLICER_STATS_READ] =
135 pipeline_fa_msg_req_policer_stats_read_handler,
136};
137
138/*
139 * Flow table
140 */
141struct meter_policer {
142 struct rte_meter_trtcm meter;
143 struct pipeline_fa_policer_params policer;
144 struct pipeline_fa_policer_stats stats;
145};
146
147struct flow_table_entry {
148 struct rte_pipeline_table_entry head;
149 struct meter_policer mp[PIPELINE_FA_N_TC_MAX];
150};
151
152static int
153flow_table_entry_set_meter(struct flow_table_entry *entry,
154 uint32_t meter_id,
155 struct pipeline_fa_flow_params *params)
156{
157 struct rte_meter_trtcm *meter = &entry->mp[meter_id].meter;
158 struct rte_meter_trtcm_params *meter_params = &params->m[meter_id];
159
160 return rte_meter_trtcm_config(meter, meter_params);
161}
162
163static void
164flow_table_entry_set_policer(struct flow_table_entry *entry,
165 uint32_t policer_id,
166 struct pipeline_fa_flow_params *params)
167{
168 struct pipeline_fa_policer_params *p0 = &entry->mp[policer_id].policer;
169 struct pipeline_fa_policer_params *p1 = &params->p[policer_id];
170
171 memcpy(p0, p1, sizeof(*p0));
172}
173
174static void
175flow_table_entry_set_port_id(struct pipeline_flow_actions *p,
176 struct flow_table_entry *entry,
177 struct pipeline_fa_flow_params *params)
178{
179 entry->head.action = RTE_PIPELINE_ACTION_PORT;
180 entry->head.port_id = p->p.port_out_id[params->port_id];
181}
182
183static int
184flow_table_entry_set_default(struct pipeline_flow_actions *p,
185 struct flow_table_entry *entry)
186{
187 struct pipeline_fa_flow_params params;
188 uint32_t i;
189
190 pipeline_fa_flow_params_set_default(&params);
191
192 memset(entry, 0, sizeof(*entry));
193
194 flow_table_entry_set_port_id(p, entry, &params);
195
196 for (i = 0; i < PIPELINE_FA_N_TC_MAX; i++) {
197 int status;
198
199 status = flow_table_entry_set_meter(entry, i, &params);
200 if (status)
201 return status;
202 }
203
204 for (i = 0; i < PIPELINE_FA_N_TC_MAX; i++)
205 flow_table_entry_set_policer(entry, i, &params);
206
207 return 0;
208}
209
210static inline uint64_t
211pkt_work(
212 struct rte_mbuf *pkt,
213 struct rte_pipeline_table_entry *table_entry,
214 void *arg,
215 uint64_t time)
216{
217 struct pipeline_flow_actions *p = arg;
218 struct flow_table_entry *entry =
219 (struct flow_table_entry *) table_entry;
220
221 struct ipv4_hdr *pkt_ip = (struct ipv4_hdr *)
222 RTE_MBUF_METADATA_UINT32_PTR(pkt, p->params.ip_hdr_offset);
223 enum rte_meter_color *pkt_color = (enum rte_meter_color *)
224 RTE_MBUF_METADATA_UINT32_PTR(pkt, p->params.color_offset);
225
226 /* Read (IP header) */
227 uint32_t total_length = rte_bswap16(pkt_ip->total_length);
228 uint32_t dscp = pkt_ip->type_of_service >> 2;
229
230 uint32_t tc = p->dscp[dscp].traffic_class;
231 enum rte_meter_color color = p->dscp[dscp].color;
232
233 struct rte_meter_trtcm *meter = &entry->mp[tc].meter;
234 struct pipeline_fa_policer_params *policer = &entry->mp[tc].policer;
235 struct pipeline_fa_policer_stats *stats = &entry->mp[tc].stats;
236
237 /* Read (entry), compute */
238 enum rte_meter_color color2 = rte_meter_trtcm_color_aware_check(meter,
239 time,
240 total_length,
241 color);
242
243 enum rte_meter_color color3 = policer->action[color2].color;
244 uint64_t drop = policer->action[color2].drop;
245
246 /* Read (entry), write (entry, color) */
247 stats->n_pkts[color3] += drop ^ 1LLU;
248 stats->n_pkts_drop += drop;
249 *pkt_color = color3;
250
251 return drop;
252}
253
254static inline uint64_t
255pkt4_work(
256 struct rte_mbuf **pkts,
257 struct rte_pipeline_table_entry **table_entries,
258 void *arg,
259 uint64_t time)
260{
261 struct pipeline_flow_actions *p = arg;
262
263 struct flow_table_entry *entry0 =
264 (struct flow_table_entry *) table_entries[0];
265 struct flow_table_entry *entry1 =
266 (struct flow_table_entry *) table_entries[1];
267 struct flow_table_entry *entry2 =
268 (struct flow_table_entry *) table_entries[2];
269 struct flow_table_entry *entry3 =
270 (struct flow_table_entry *) table_entries[3];
271
272 struct ipv4_hdr *pkt0_ip = (struct ipv4_hdr *)
273 RTE_MBUF_METADATA_UINT32_PTR(pkts[0], p->params.ip_hdr_offset);
274 struct ipv4_hdr *pkt1_ip = (struct ipv4_hdr *)
275 RTE_MBUF_METADATA_UINT32_PTR(pkts[1], p->params.ip_hdr_offset);
276 struct ipv4_hdr *pkt2_ip = (struct ipv4_hdr *)
277 RTE_MBUF_METADATA_UINT32_PTR(pkts[2], p->params.ip_hdr_offset);
278 struct ipv4_hdr *pkt3_ip = (struct ipv4_hdr *)
279 RTE_MBUF_METADATA_UINT32_PTR(pkts[3], p->params.ip_hdr_offset);
280
281 enum rte_meter_color *pkt0_color = (enum rte_meter_color *)
282 RTE_MBUF_METADATA_UINT32_PTR(pkts[0], p->params.color_offset);
283 enum rte_meter_color *pkt1_color = (enum rte_meter_color *)
284 RTE_MBUF_METADATA_UINT32_PTR(pkts[1], p->params.color_offset);
285 enum rte_meter_color *pkt2_color = (enum rte_meter_color *)
286 RTE_MBUF_METADATA_UINT32_PTR(pkts[2], p->params.color_offset);
287 enum rte_meter_color *pkt3_color = (enum rte_meter_color *)
288 RTE_MBUF_METADATA_UINT32_PTR(pkts[3], p->params.color_offset);
289
290 /* Read (IP header) */
291 uint32_t total_length0 = rte_bswap16(pkt0_ip->total_length);
292 uint32_t dscp0 = pkt0_ip->type_of_service >> 2;
293
294 uint32_t total_length1 = rte_bswap16(pkt1_ip->total_length);
295 uint32_t dscp1 = pkt1_ip->type_of_service >> 2;
296
297 uint32_t total_length2 = rte_bswap16(pkt2_ip->total_length);
298 uint32_t dscp2 = pkt2_ip->type_of_service >> 2;
299
300 uint32_t total_length3 = rte_bswap16(pkt3_ip->total_length);
301 uint32_t dscp3 = pkt3_ip->type_of_service >> 2;
302
303 uint32_t tc0 = p->dscp[dscp0].traffic_class;
304 enum rte_meter_color color0 = p->dscp[dscp0].color;
305
306 uint32_t tc1 = p->dscp[dscp1].traffic_class;
307 enum rte_meter_color color1 = p->dscp[dscp1].color;
308
309 uint32_t tc2 = p->dscp[dscp2].traffic_class;
310 enum rte_meter_color color2 = p->dscp[dscp2].color;
311
312 uint32_t tc3 = p->dscp[dscp3].traffic_class;
313 enum rte_meter_color color3 = p->dscp[dscp3].color;
314
315 struct rte_meter_trtcm *meter0 = &entry0->mp[tc0].meter;
316 struct pipeline_fa_policer_params *policer0 = &entry0->mp[tc0].policer;
317 struct pipeline_fa_policer_stats *stats0 = &entry0->mp[tc0].stats;
318
319 struct rte_meter_trtcm *meter1 = &entry1->mp[tc1].meter;
320 struct pipeline_fa_policer_params *policer1 = &entry1->mp[tc1].policer;
321 struct pipeline_fa_policer_stats *stats1 = &entry1->mp[tc1].stats;
322
323 struct rte_meter_trtcm *meter2 = &entry2->mp[tc2].meter;
324 struct pipeline_fa_policer_params *policer2 = &entry2->mp[tc2].policer;
325 struct pipeline_fa_policer_stats *stats2 = &entry2->mp[tc2].stats;
326
327 struct rte_meter_trtcm *meter3 = &entry3->mp[tc3].meter;
328 struct pipeline_fa_policer_params *policer3 = &entry3->mp[tc3].policer;
329 struct pipeline_fa_policer_stats *stats3 = &entry3->mp[tc3].stats;
330
331 /* Read (entry), compute, write (entry) */
332 enum rte_meter_color color2_0 = rte_meter_trtcm_color_aware_check(
333 meter0,
334 time,
335 total_length0,
336 color0);
337
338 enum rte_meter_color color2_1 = rte_meter_trtcm_color_aware_check(
339 meter1,
340 time,
341 total_length1,
342 color1);
343
344 enum rte_meter_color color2_2 = rte_meter_trtcm_color_aware_check(
345 meter2,
346 time,
347 total_length2,
348 color2);
349
350 enum rte_meter_color color2_3 = rte_meter_trtcm_color_aware_check(
351 meter3,
352 time,
353 total_length3,
354 color3);
355
356 enum rte_meter_color color3_0 = policer0->action[color2_0].color;
357 enum rte_meter_color color3_1 = policer1->action[color2_1].color;
358 enum rte_meter_color color3_2 = policer2->action[color2_2].color;
359 enum rte_meter_color color3_3 = policer3->action[color2_3].color;
360
361 uint64_t drop0 = policer0->action[color2_0].drop;
362 uint64_t drop1 = policer1->action[color2_1].drop;
363 uint64_t drop2 = policer2->action[color2_2].drop;
364 uint64_t drop3 = policer3->action[color2_3].drop;
365
366 /* Read (entry), write (entry, color) */
367 stats0->n_pkts[color3_0] += drop0 ^ 1LLU;
368 stats0->n_pkts_drop += drop0;
369
370 stats1->n_pkts[color3_1] += drop1 ^ 1LLU;
371 stats1->n_pkts_drop += drop1;
372
373 stats2->n_pkts[color3_2] += drop2 ^ 1LLU;
374 stats2->n_pkts_drop += drop2;
375
376 stats3->n_pkts[color3_3] += drop3 ^ 1LLU;
377 stats3->n_pkts_drop += drop3;
378
379 *pkt0_color = color3_0;
380 *pkt1_color = color3_1;
381 *pkt2_color = color3_2;
382 *pkt3_color = color3_3;
383
384 return drop0 | (drop1 << 1) | (drop2 << 2) | (drop3 << 3);
385}
386
387PIPELINE_TABLE_AH_HIT_DROP_TIME(fa_table_ah_hit, pkt_work, pkt4_work);
388
389static rte_pipeline_table_action_handler_hit
390get_fa_table_ah_hit(__rte_unused struct pipeline_flow_actions *p)
391{
392 return fa_table_ah_hit;
393}
394
395/*
396 * Argument parsing
397 */
398int
399pipeline_fa_parse_args(struct pipeline_fa_params *p,
400 struct pipeline_params *params)
401{
402 uint32_t n_flows_present = 0;
403 uint32_t n_meters_per_flow_present = 0;
404 uint32_t flow_id_offset_present = 0;
405 uint32_t ip_hdr_offset_present = 0;
406 uint32_t color_offset_present = 0;
407 uint32_t i;
408
409 /* Default values */
410 p->n_meters_per_flow = 1;
411 p->dscp_enabled = 0;
412
413 for (i = 0; i < params->n_args; i++) {
414 char *arg_name = params->args_name[i];
415 char *arg_value = params->args_value[i];
416
417 /* n_flows */
418 if (strcmp(arg_name, "n_flows") == 0) {
419 int status;
420
421 PIPELINE_PARSE_ERR_DUPLICATE(
422 n_flows_present == 0, params->name,
423 arg_name);
424 n_flows_present = 1;
425
426 status = parser_read_uint32(&p->n_flows,
427 arg_value);
428 PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&
429 (p->n_flows != 0)), params->name,
430 arg_name, arg_value);
431 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
432 params->name, arg_name, arg_value);
433
434 continue;
435 }
436
437 /* n_meters_per_flow */
438 if (strcmp(arg_name, "n_meters_per_flow") == 0) {
439 int status;
440
441 PIPELINE_PARSE_ERR_DUPLICATE(
442 n_meters_per_flow_present == 0,
443 params->name, arg_name);
444 n_meters_per_flow_present = 1;
445
446 status = parser_read_uint32(&p->n_meters_per_flow,
447 arg_value);
448 PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) &&
449 (p->n_meters_per_flow != 0)),
450 params->name, arg_name, arg_value);
451 PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) &&
452 (p->n_meters_per_flow <=
453 PIPELINE_FA_N_TC_MAX)), params->name,
454 arg_name, arg_value);
455
456 continue;
457 }
458
459 /* flow_id_offset */
460 if (strcmp(arg_name, "flow_id_offset") == 0) {
461 int status;
462
463 PIPELINE_PARSE_ERR_DUPLICATE(
464 flow_id_offset_present == 0,
465 params->name, arg_name);
466 flow_id_offset_present = 1;
467
468 status = parser_read_uint32(&p->flow_id_offset,
469 arg_value);
470 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
471 params->name, arg_name, arg_value);
472 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
473 params->name, arg_name, arg_value);
474
475 continue;
476 }
477
478 /* ip_hdr_offset */
479 if (strcmp(arg_name, "ip_hdr_offset") == 0) {
480 int status;
481
482 PIPELINE_PARSE_ERR_DUPLICATE(
483 ip_hdr_offset_present == 0,
484 params->name, arg_name);
485 ip_hdr_offset_present = 1;
486
487 status = parser_read_uint32(&p->ip_hdr_offset,
488 arg_value);
489 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
490 params->name, arg_name, arg_value);
491 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
492 params->name, arg_name, arg_value);
493
494 continue;
495 }
496
497 /* color_offset */
498 if (strcmp(arg_name, "color_offset") == 0) {
499 int status;
500
501 PIPELINE_PARSE_ERR_DUPLICATE(
502 color_offset_present == 0, params->name,
503 arg_name);
504 color_offset_present = 1;
505
506 status = parser_read_uint32(&p->color_offset,
507 arg_value);
508 PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL),
509 params->name, arg_name, arg_value);
510 PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE),
511 params->name, arg_name, arg_value);
512
513 p->dscp_enabled = 1;
514
515 continue;
516 }
517
518 /* Unknown argument */
519 PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name);
520 }
521
522 /* Check that mandatory arguments are present */
523 PIPELINE_PARSE_ERR_MANDATORY((n_flows_present), params->name,
524 "n_flows");
525 PIPELINE_PARSE_ERR_MANDATORY((flow_id_offset_present),
526 params->name, "flow_id_offset");
527 PIPELINE_PARSE_ERR_MANDATORY((ip_hdr_offset_present),
528 params->name, "ip_hdr_offset");
529 PIPELINE_PARSE_ERR_MANDATORY((color_offset_present), params->name,
530 "color_offset");
531
532 return 0;
533}
534
535static void
536dscp_init(struct pipeline_flow_actions *p)
537{
538 uint32_t i;
539
540 for (i = 0; i < PIPELINE_FA_N_DSCP; i++) {
541 p->dscp[i].traffic_class = 0;
542 p->dscp[i].color = e_RTE_METER_GREEN;
543 }
544}
545
546static void *pipeline_fa_init(struct pipeline_params *params,
547 __rte_unused void *arg)
548{
549 struct pipeline *p;
550 struct pipeline_flow_actions *p_fa;
551 uint32_t size, i;
552
553 /* Check input arguments */
554 if (params == NULL)
555 return NULL;
556
557 if (params->n_ports_in != params->n_ports_out)
558 return NULL;
559
560 /* Memory allocation */
561 size = RTE_CACHE_LINE_ROUNDUP(
562 sizeof(struct pipeline_flow_actions));
563 p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
564 if (p == NULL)
565 return NULL;
566 p_fa = (struct pipeline_flow_actions *) p;
567
568 strcpy(p->name, params->name);
569 p->log_level = params->log_level;
570
571 PLOG(p, HIGH, "Flow actions");
572
573 /* Parse arguments */
574 if (pipeline_fa_parse_args(&p_fa->params, params))
575 return NULL;
576
577 dscp_init(p_fa);
578
579 /* Pipeline */
580 {
581 struct rte_pipeline_params pipeline_params = {
582 .name = params->name,
583 .socket_id = params->socket_id,
584 .offset_port_id = 0,
585 };
586
587 p->p = rte_pipeline_create(&pipeline_params);
588 if (p->p == NULL) {
589 rte_free(p);
590 return NULL;
591 }
592 }
593
594 /* Input ports */
595 p->n_ports_in = params->n_ports_in;
596 for (i = 0; i < p->n_ports_in; i++) {
597 struct rte_pipeline_port_in_params port_params = {
598 .ops = pipeline_port_in_params_get_ops(
599 &params->port_in[i]),
600 .arg_create = pipeline_port_in_params_convert(
601 &params->port_in[i]),
602 .f_action = NULL,
603 .arg_ah = NULL,
604 .burst_size = params->port_in[i].burst_size,
605 };
606
607 int status = rte_pipeline_port_in_create(p->p,
608 &port_params,
609 &p->port_in_id[i]);
610
611 if (status) {
612 rte_pipeline_free(p->p);
613 rte_free(p);
614 return NULL;
615 }
616 }
617
618 /* Output ports */
619 p->n_ports_out = params->n_ports_out;
620 for (i = 0; i < p->n_ports_out; i++) {
621 struct rte_pipeline_port_out_params port_params = {
622 .ops = pipeline_port_out_params_get_ops(
623 &params->port_out[i]),
624 .arg_create = pipeline_port_out_params_convert(
625 &params->port_out[i]),
626 .f_action = NULL,
627 .arg_ah = NULL,
628 };
629
630 int status = rte_pipeline_port_out_create(p->p,
631 &port_params,
632 &p->port_out_id[i]);
633
634 if (status) {
635 rte_pipeline_free(p->p);
636 rte_free(p);
637 return NULL;
638 }
639 }
640
641 /* Tables */
642 p->n_tables = 1;
643 {
644 struct rte_table_array_params table_array_params = {
645 .n_entries = p_fa->params.n_flows,
646 .offset = p_fa->params.flow_id_offset,
647 };
648
649 struct rte_pipeline_table_params table_params = {
650 .ops = &rte_table_array_ops,
651 .arg_create = &table_array_params,
652 .f_action_hit = get_fa_table_ah_hit(p_fa),
653 .f_action_miss = NULL,
654 .arg_ah = p_fa,
655 .action_data_size =
656 sizeof(struct flow_table_entry) -
657 sizeof(struct rte_pipeline_table_entry),
658 };
659
660 int status;
661
662 status = rte_pipeline_table_create(p->p,
663 &table_params,
664 &p->table_id[0]);
665
666 if (status) {
667 rte_pipeline_free(p->p);
668 rte_free(p);
669 return NULL;
670 }
671 }
672
673 /* Connecting input ports to tables */
674 for (i = 0; i < p->n_ports_in; i++) {
675 int status = rte_pipeline_port_in_connect_to_table(p->p,
676 p->port_in_id[i],
677 p->table_id[0]);
678
679 if (status) {
680 rte_pipeline_free(p->p);
681 rte_free(p);
682 return NULL;
683 }
684 }
685
686 /* Enable input ports */
687 for (i = 0; i < p->n_ports_in; i++) {
688 int status = rte_pipeline_port_in_enable(p->p,
689 p->port_in_id[i]);
690
691 if (status) {
692 rte_pipeline_free(p->p);
693 rte_free(p);
694 return NULL;
695 }
696 }
697
698 /* Initialize table entries */
699 for (i = 0; i < p_fa->params.n_flows; i++) {
700 struct rte_table_array_key key = {
701 .pos = i,
702 };
703
704 struct flow_table_entry entry;
705 struct rte_pipeline_table_entry *entry_ptr;
706 int key_found, status;
707
708 flow_table_entry_set_default(p_fa, &entry);
709
710 status = rte_pipeline_table_entry_add(p->p,
711 p->table_id[0],
712 &key,
713 (struct rte_pipeline_table_entry *) &entry,
714 &key_found,
715 &entry_ptr);
716
717 if (status) {
718 rte_pipeline_free(p->p);
719 rte_free(p);
720 return NULL;
721 }
722 }
723
724 /* Check pipeline consistency */
725 if (rte_pipeline_check(p->p) < 0) {
726 rte_pipeline_free(p->p);
727 rte_free(p);
728 return NULL;
729 }
730
731 /* Message queues */
732 p->n_msgq = params->n_msgq;
733 for (i = 0; i < p->n_msgq; i++)
734 p->msgq_in[i] = params->msgq_in[i];
735 for (i = 0; i < p->n_msgq; i++)
736 p->msgq_out[i] = params->msgq_out[i];
737
738 /* Message handlers */
739 memcpy(p->handlers, handlers, sizeof(p->handlers));
740 memcpy(p_fa->custom_handlers,
741 custom_handlers,
742 sizeof(p_fa->custom_handlers));
743
744 return p;
745}
746
747static int
748pipeline_fa_free(void *pipeline)
749{
750 struct pipeline *p = (struct pipeline *) pipeline;
751
752 /* Check input arguments */
753 if (p == NULL)
754 return -1;
755
756 /* Free resources */
757 rte_pipeline_free(p->p);
758 rte_free(p);
759 return 0;
760}
761
762static int
763pipeline_fa_timer(void *pipeline)
764{
765 struct pipeline *p = (struct pipeline *) pipeline;
766
767 pipeline_msg_req_handle(p);
768 rte_pipeline_flush(p->p);
769
770 return 0;
771}
772
773void *
774pipeline_fa_msg_req_custom_handler(struct pipeline *p, void *msg)
775{
776 struct pipeline_flow_actions *p_fa =
777 (struct pipeline_flow_actions *) p;
778 struct pipeline_custom_msg_req *req = msg;
779 pipeline_msg_req_handler f_handle;
780
781 f_handle = (req->subtype < PIPELINE_FA_MSG_REQS) ?
782 p_fa->custom_handlers[req->subtype] :
783 pipeline_msg_req_invalid_handler;
784
785 if (f_handle == NULL)
786 f_handle = pipeline_msg_req_invalid_handler;
787
788 return f_handle(p, req);
789}
790
791void *
792pipeline_fa_msg_req_flow_config_handler(struct pipeline *p, void *msg)
793{
794 struct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p;
795 struct pipeline_fa_flow_config_msg_req *req = msg;
796 struct pipeline_fa_flow_config_msg_rsp *rsp = msg;
797 struct flow_table_entry *entry;
798 uint32_t mask, i;
799
800 /* Set flow table entry to default if not configured before */
801 if (req->entry_ptr == NULL) {
802 struct rte_table_array_key key = {
803 .pos = req->flow_id % p_fa->params.n_flows,
804 };
805
806 struct flow_table_entry default_entry;
807
808 int key_found, status;
809
810 flow_table_entry_set_default(p_fa, &default_entry);
811
812 status = rte_pipeline_table_entry_add(p->p,
813 p->table_id[0],
814 &key,
815 (struct rte_pipeline_table_entry *) &default_entry,
816 &key_found,
817 (struct rte_pipeline_table_entry **) &entry);
818 if (status) {
819 rsp->status = -1;
820 return rsp;
821 }
822 } else
823 entry = (struct flow_table_entry *) req->entry_ptr;
824
825 /* Meter */
826 for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {
827 int status;
828
829 if ((mask & req->meter_update_mask) == 0)
830 continue;
831
832 status = flow_table_entry_set_meter(entry, i, &req->params);
833 if (status) {
834 rsp->status = -1;
835 return rsp;
836 }
837 }
838
839 /* Policer */
840 for (i = 0, mask = 1; i < PIPELINE_FA_N_TC_MAX; i++, mask <<= 1) {
841 if ((mask & req->policer_update_mask) == 0)
842 continue;
843
844 flow_table_entry_set_policer(entry, i, &req->params);
845 }
846
847 /* Port */
848 if (req->port_update)
849 flow_table_entry_set_port_id(p_fa, entry, &req->params);
850
851 /* Response */
852 rsp->status = 0;
853 rsp->entry_ptr = (void *) entry;
854 return rsp;
855}
856
857void *
858pipeline_fa_msg_req_flow_config_bulk_handler(struct pipeline *p, void *msg)
859{
860 struct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p;
861 struct pipeline_fa_flow_config_bulk_msg_req *req = msg;
862 struct pipeline_fa_flow_config_bulk_msg_rsp *rsp = msg;
863 uint32_t i;
864
865 for (i = 0; i < req->n_flows; i++) {
866 struct flow_table_entry *entry;
867 uint32_t j, mask;
868
869 /* Set flow table entry to default if not configured before */
870 if (req->entry_ptr[i] == NULL) {
871 struct rte_table_array_key key = {
872 .pos = req->flow_id[i] % p_fa->params.n_flows,
873 };
874
875 struct flow_table_entry entry_to_add;
876
877 int key_found, status;
878
879 flow_table_entry_set_default(p_fa, &entry_to_add);
880
881 status = rte_pipeline_table_entry_add(p->p,
882 p->table_id[0],
883 &key,
884 (struct rte_pipeline_table_entry *) &entry_to_add,
885 &key_found,
886 (struct rte_pipeline_table_entry **) &entry);
887 if (status) {
888 rsp->n_flows = i;
889 return rsp;
890 }
891
892 req->entry_ptr[i] = (void *) entry;
893 } else
894 entry = (struct flow_table_entry *) req->entry_ptr[i];
895
896 /* Meter */
897 for (j = 0, mask = 1;
898 j < PIPELINE_FA_N_TC_MAX;
899 j++, mask <<= 1) {
900 int status;
901
902 if ((mask & req->meter_update_mask) == 0)
903 continue;
904
905 status = flow_table_entry_set_meter(entry,
906 j, &req->params[i]);
907 if (status) {
908 rsp->n_flows = i;
909 return rsp;
910 }
911 }
912
913 /* Policer */
914 for (j = 0, mask = 1;
915 j < PIPELINE_FA_N_TC_MAX;
916 j++, mask <<= 1) {
917 if ((mask & req->policer_update_mask) == 0)
918 continue;
919
920 flow_table_entry_set_policer(entry,
921 j, &req->params[i]);
922 }
923
924 /* Port */
925 if (req->port_update)
926 flow_table_entry_set_port_id(p_fa,
927 entry, &req->params[i]);
928 }
929
930 /* Response */
931 rsp->n_flows = i;
932 return rsp;
933}
934
935void *
936pipeline_fa_msg_req_dscp_config_handler(struct pipeline *p, void *msg)
937{
938 struct pipeline_flow_actions *p_fa = (struct pipeline_flow_actions *) p;
939 struct pipeline_fa_dscp_config_msg_req *req = msg;
940 struct pipeline_fa_dscp_config_msg_rsp *rsp = msg;
941
942 /* Check request */
943 if ((req->dscp >= PIPELINE_FA_N_DSCP) ||
944 (req->traffic_class >= PIPELINE_FA_N_TC_MAX) ||
945 (req->color >= e_RTE_METER_COLORS)) {
946 rsp->status = -1;
947 return rsp;
948 }
949
950 p_fa->dscp[req->dscp].traffic_class = req->traffic_class;
951 p_fa->dscp[req->dscp].color = req->color;
952 rsp->status = 0;
953 return rsp;
954}
955
956void *
957pipeline_fa_msg_req_policer_stats_read_handler(__rte_unused struct pipeline *p,
958 void *msg)
959{
960 struct pipeline_fa_policer_stats_msg_req *req = msg;
961 struct pipeline_fa_policer_stats_msg_rsp *rsp = msg;
962
963 struct flow_table_entry *entry = req->entry_ptr;
964 uint32_t policer_id = req->policer_id;
965 int clear = req->clear;
966
967 /* Check request */
968 if ((req->entry_ptr == NULL) ||
969 (req->policer_id >= PIPELINE_FA_N_TC_MAX)) {
970 rsp->status = -1;
971 return rsp;
972 }
973
974 memcpy(&rsp->stats,
975 &entry->mp[policer_id].stats,
976 sizeof(rsp->stats));
977 if (clear)
978 memset(&entry->mp[policer_id].stats,
979 0, sizeof(entry->mp[policer_id].stats));
980 rsp->status = 0;
981 return rsp;
982}
983
984struct pipeline_be_ops pipeline_flow_actions_be_ops = {
985 .f_init = pipeline_fa_init,
986 .f_free = pipeline_fa_free,
987 .f_run = NULL,
988 .f_timer = pipeline_fa_timer,
989};