Imported Upstream version 16.07-rc1
[deb_dpdk.git] / examples / ip_pipeline / pipeline / pipeline_flow_actions_be.c
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
48 int
49 pipeline_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
82 struct dscp_entry {
83         uint32_t traffic_class;
84         enum rte_meter_color color;
85 };
86
87 struct 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
95 static void *
96 pipeline_fa_msg_req_custom_handler(struct pipeline *p, void *msg);
97
98 static 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
115 static void *
116 pipeline_fa_msg_req_flow_config_handler(struct pipeline *p, void *msg);
117
118 static void *
119 pipeline_fa_msg_req_flow_config_bulk_handler(struct pipeline *p, void *msg);
120
121 static void *
122 pipeline_fa_msg_req_dscp_config_handler(struct pipeline *p, void *msg);
123
124 static void *
125 pipeline_fa_msg_req_policer_stats_read_handler(struct pipeline *p, void *msg);
126
127 static 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  */
141 struct meter_policer {
142         struct rte_meter_trtcm meter;
143         struct pipeline_fa_policer_params policer;
144         struct pipeline_fa_policer_stats stats;
145 };
146
147 struct flow_table_entry {
148         struct rte_pipeline_table_entry head;
149         struct meter_policer mp[PIPELINE_FA_N_TC_MAX];
150 };
151
152 static int
153 flow_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
163 static void
164 flow_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
174 static void
175 flow_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
183 static int
184 flow_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
210 static inline uint64_t
211 pkt_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
254 static inline uint64_t
255 pkt4_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
387 PIPELINE_TABLE_AH_HIT_DROP_TIME(fa_table_ah_hit, pkt_work, pkt4_work);
388
389 static rte_pipeline_table_action_handler_hit
390 get_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  */
398 int
399 pipeline_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
535 static void
536 dscp_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
546 static 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
747 static int
748 pipeline_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
762 static int
763 pipeline_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
773 void *
774 pipeline_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
791 void *
792 pipeline_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
857 void *
858 pipeline_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
935 void *
936 pipeline_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
956 void *
957 pipeline_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
984 struct 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 };