cryptodev: add asymmetric session user data API
[dpdk.git] / examples / ip_pipeline / thread.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2018 Intel Corporation
3  */
4
5 #include <stdlib.h>
6
7 #include <rte_common.h>
8 #include <rte_cycles.h>
9 #include <rte_lcore.h>
10 #include <rte_ring.h>
11
12 #include <rte_table_acl.h>
13 #include <rte_table_array.h>
14 #include <rte_table_hash.h>
15 #include <rte_table_lpm.h>
16 #include <rte_table_lpm_ipv6.h>
17
18 #include "common.h"
19 #include "thread.h"
20 #include "pipeline.h"
21
22 #ifndef THREAD_PIPELINES_MAX
23 #define THREAD_PIPELINES_MAX                               256
24 #endif
25
26 #ifndef THREAD_MSGQ_SIZE
27 #define THREAD_MSGQ_SIZE                                   64
28 #endif
29
30 #ifndef THREAD_TIMER_PERIOD_MS
31 #define THREAD_TIMER_PERIOD_MS                             100
32 #endif
33
34 /**
35  * Main thread: data plane thread context
36  */
37 struct thread {
38         struct rte_ring *msgq_req;
39         struct rte_ring *msgq_rsp;
40
41         uint32_t enabled;
42 };
43
44 static struct thread thread[RTE_MAX_LCORE];
45
46 /**
47  * Data plane threads: context
48  */
49 struct table_data {
50         struct rte_table_action *a;
51 };
52
53 struct pipeline_data {
54         struct rte_pipeline *p;
55         struct table_data table_data[RTE_PIPELINE_TABLE_MAX];
56         uint32_t n_tables;
57
58         struct rte_ring *msgq_req;
59         struct rte_ring *msgq_rsp;
60         uint64_t timer_period; /* Measured in CPU cycles. */
61         uint64_t time_next;
62
63         uint8_t buffer[TABLE_RULE_ACTION_SIZE_MAX];
64 };
65
66 struct thread_data {
67         struct rte_pipeline *p[THREAD_PIPELINES_MAX];
68         uint32_t n_pipelines;
69
70         struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX];
71         struct rte_ring *msgq_req;
72         struct rte_ring *msgq_rsp;
73         uint64_t timer_period; /* Measured in CPU cycles. */
74         uint64_t time_next;
75         uint64_t time_next_min;
76 } __rte_cache_aligned;
77
78 static struct thread_data thread_data[RTE_MAX_LCORE];
79
80 /**
81  * Main thread: data plane thread init
82  */
83 static void
84 thread_free(void)
85 {
86         uint32_t i;
87
88         for (i = 0; i < RTE_MAX_LCORE; i++) {
89                 struct thread *t = &thread[i];
90
91                 if (!rte_lcore_is_enabled(i))
92                         continue;
93
94                 /* MSGQs */
95                 rte_ring_free(t->msgq_req);
96
97                 rte_ring_free(t->msgq_rsp);
98         }
99 }
100
101 int
102 thread_init(void)
103 {
104         uint32_t i;
105
106         RTE_LCORE_FOREACH_WORKER(i) {
107                 char name[NAME_MAX];
108                 struct rte_ring *msgq_req, *msgq_rsp;
109                 struct thread *t = &thread[i];
110                 struct thread_data *t_data = &thread_data[i];
111                 uint32_t cpu_id = rte_lcore_to_socket_id(i);
112
113                 /* MSGQs */
114                 snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-REQ", i);
115
116                 msgq_req = rte_ring_create(name,
117                         THREAD_MSGQ_SIZE,
118                         cpu_id,
119                         RING_F_SP_ENQ | RING_F_SC_DEQ);
120
121                 if (msgq_req == NULL) {
122                         thread_free();
123                         return -1;
124                 }
125
126                 snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-RSP", i);
127
128                 msgq_rsp = rte_ring_create(name,
129                         THREAD_MSGQ_SIZE,
130                         cpu_id,
131                         RING_F_SP_ENQ | RING_F_SC_DEQ);
132
133                 if (msgq_rsp == NULL) {
134                         thread_free();
135                         return -1;
136                 }
137
138                 /* Main thread records */
139                 t->msgq_req = msgq_req;
140                 t->msgq_rsp = msgq_rsp;
141                 t->enabled = 1;
142
143                 /* Data plane thread records */
144                 t_data->n_pipelines = 0;
145                 t_data->msgq_req = msgq_req;
146                 t_data->msgq_rsp = msgq_rsp;
147                 t_data->timer_period =
148                         (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
149                 t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
150                 t_data->time_next_min = t_data->time_next;
151         }
152
153         return 0;
154 }
155
156 static inline int
157 thread_is_running(uint32_t thread_id)
158 {
159         enum rte_lcore_state_t thread_state;
160
161         thread_state = rte_eal_get_lcore_state(thread_id);
162         return (thread_state == RUNNING) ? 1 : 0;
163 }
164
165 /**
166  * Pipeline is running when:
167  *    (A) Pipeline is mapped to a data plane thread AND
168  *    (B) Its data plane thread is in RUNNING state.
169  */
170 static inline int
171 pipeline_is_running(struct pipeline *p)
172 {
173         if (p->enabled == 0)
174                 return 0;
175
176         return thread_is_running(p->thread_id);
177 }
178
179 /**
180  * Main thread & data plane threads: message passing
181  */
182 enum thread_req_type {
183         THREAD_REQ_PIPELINE_ENABLE = 0,
184         THREAD_REQ_PIPELINE_DISABLE,
185         THREAD_REQ_MAX
186 };
187
188 struct thread_msg_req {
189         enum thread_req_type type;
190
191         union {
192                 struct {
193                         struct rte_pipeline *p;
194                         struct {
195                                 struct rte_table_action *a;
196                         } table[RTE_PIPELINE_TABLE_MAX];
197                         struct rte_ring *msgq_req;
198                         struct rte_ring *msgq_rsp;
199                         uint32_t timer_period_ms;
200                         uint32_t n_tables;
201                 } pipeline_enable;
202
203                 struct {
204                         struct rte_pipeline *p;
205                 } pipeline_disable;
206         };
207 };
208
209 struct thread_msg_rsp {
210         int status;
211 };
212
213 /**
214  * Main thread
215  */
216 static struct thread_msg_req *
217 thread_msg_alloc(void)
218 {
219         size_t size = RTE_MAX(sizeof(struct thread_msg_req),
220                 sizeof(struct thread_msg_rsp));
221
222         return calloc(1, size);
223 }
224
225 static void
226 thread_msg_free(struct thread_msg_rsp *rsp)
227 {
228         free(rsp);
229 }
230
231 static struct thread_msg_rsp *
232 thread_msg_send_recv(uint32_t thread_id,
233         struct thread_msg_req *req)
234 {
235         struct thread *t = &thread[thread_id];
236         struct rte_ring *msgq_req = t->msgq_req;
237         struct rte_ring *msgq_rsp = t->msgq_rsp;
238         struct thread_msg_rsp *rsp;
239         int status;
240
241         /* send */
242         do {
243                 status = rte_ring_sp_enqueue(msgq_req, req);
244         } while (status == -ENOBUFS);
245
246         /* recv */
247         do {
248                 status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp);
249         } while (status != 0);
250
251         return rsp;
252 }
253
254 int
255 thread_pipeline_enable(uint32_t thread_id,
256         const char *pipeline_name)
257 {
258         struct pipeline *p = pipeline_find(pipeline_name);
259         struct thread *t;
260         struct thread_msg_req *req;
261         struct thread_msg_rsp *rsp;
262         uint32_t i;
263         int status;
264
265         /* Check input params */
266         if ((thread_id >= RTE_MAX_LCORE) ||
267                 (p == NULL) ||
268                 (p->n_ports_in == 0) ||
269                 (p->n_ports_out == 0) ||
270                 (p->n_tables == 0))
271                 return -1;
272
273         t = &thread[thread_id];
274         if ((t->enabled == 0) ||
275                 p->enabled)
276                 return -1;
277
278         if (!thread_is_running(thread_id)) {
279                 struct thread_data *td = &thread_data[thread_id];
280                 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
281
282                 if (td->n_pipelines >= THREAD_PIPELINES_MAX)
283                         return -1;
284
285                 /* Data plane thread */
286                 td->p[td->n_pipelines] = p->p;
287
288                 tdp->p = p->p;
289                 for (i = 0; i < p->n_tables; i++)
290                         tdp->table_data[i].a = p->table[i].a;
291
292                 tdp->n_tables = p->n_tables;
293
294                 tdp->msgq_req = p->msgq_req;
295                 tdp->msgq_rsp = p->msgq_rsp;
296                 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
297                 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
298
299                 td->n_pipelines++;
300
301                 /* Pipeline */
302                 p->thread_id = thread_id;
303                 p->enabled = 1;
304
305                 return 0;
306         }
307
308         /* Allocate request */
309         req = thread_msg_alloc();
310         if (req == NULL)
311                 return -1;
312
313         /* Write request */
314         req->type = THREAD_REQ_PIPELINE_ENABLE;
315         req->pipeline_enable.p = p->p;
316         for (i = 0; i < p->n_tables; i++)
317                 req->pipeline_enable.table[i].a =
318                         p->table[i].a;
319         req->pipeline_enable.msgq_req = p->msgq_req;
320         req->pipeline_enable.msgq_rsp = p->msgq_rsp;
321         req->pipeline_enable.timer_period_ms = p->timer_period_ms;
322         req->pipeline_enable.n_tables = p->n_tables;
323
324         /* Send request and wait for response */
325         rsp = thread_msg_send_recv(thread_id, req);
326
327         /* Read response */
328         status = rsp->status;
329
330         /* Free response */
331         thread_msg_free(rsp);
332
333         /* Request completion */
334         if (status)
335                 return status;
336
337         p->thread_id = thread_id;
338         p->enabled = 1;
339
340         return 0;
341 }
342
343 int
344 thread_pipeline_disable(uint32_t thread_id,
345         const char *pipeline_name)
346 {
347         struct pipeline *p = pipeline_find(pipeline_name);
348         struct thread *t;
349         struct thread_msg_req *req;
350         struct thread_msg_rsp *rsp;
351         int status;
352
353         /* Check input params */
354         if ((thread_id >= RTE_MAX_LCORE) ||
355                 (p == NULL))
356                 return -1;
357
358         t = &thread[thread_id];
359         if (t->enabled == 0)
360                 return -1;
361
362         if (p->enabled == 0)
363                 return 0;
364
365         if (p->thread_id != thread_id)
366                 return -1;
367
368         if (!thread_is_running(thread_id)) {
369                 struct thread_data *td = &thread_data[thread_id];
370                 uint32_t i;
371
372                 for (i = 0; i < td->n_pipelines; i++) {
373                         struct pipeline_data *tdp = &td->pipeline_data[i];
374
375                         if (tdp->p != p->p)
376                                 continue;
377
378                         /* Data plane thread */
379                         if (i < td->n_pipelines - 1) {
380                                 struct rte_pipeline *pipeline_last =
381                                         td->p[td->n_pipelines - 1];
382                                 struct pipeline_data *tdp_last =
383                                         &td->pipeline_data[td->n_pipelines - 1];
384
385                                 td->p[i] = pipeline_last;
386                                 memcpy(tdp, tdp_last, sizeof(*tdp));
387                         }
388
389                         td->n_pipelines--;
390
391                         /* Pipeline */
392                         p->enabled = 0;
393
394                         break;
395                 }
396
397                 return 0;
398         }
399
400         /* Allocate request */
401         req = thread_msg_alloc();
402         if (req == NULL)
403                 return -1;
404
405         /* Write request */
406         req->type = THREAD_REQ_PIPELINE_DISABLE;
407         req->pipeline_disable.p = p->p;
408
409         /* Send request and wait for response */
410         rsp = thread_msg_send_recv(thread_id, req);
411
412         /* Read response */
413         status = rsp->status;
414
415         /* Free response */
416         thread_msg_free(rsp);
417
418         /* Request completion */
419         if (status)
420                 return status;
421
422         p->enabled = 0;
423
424         return 0;
425 }
426
427 /**
428  * Data plane threads: message handling
429  */
430 static inline struct thread_msg_req *
431 thread_msg_recv(struct rte_ring *msgq_req)
432 {
433         struct thread_msg_req *req;
434
435         int status = rte_ring_sc_dequeue(msgq_req, (void **) &req);
436
437         if (status != 0)
438                 return NULL;
439
440         return req;
441 }
442
443 static inline void
444 thread_msg_send(struct rte_ring *msgq_rsp,
445         struct thread_msg_rsp *rsp)
446 {
447         int status;
448
449         do {
450                 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
451         } while (status == -ENOBUFS);
452 }
453
454 static struct thread_msg_rsp *
455 thread_msg_handle_pipeline_enable(struct thread_data *t,
456         struct thread_msg_req *req)
457 {
458         struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req;
459         struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
460         uint32_t i;
461
462         /* Request */
463         if (t->n_pipelines >= THREAD_PIPELINES_MAX) {
464                 rsp->status = -1;
465                 return rsp;
466         }
467
468         t->p[t->n_pipelines] = req->pipeline_enable.p;
469
470         p->p = req->pipeline_enable.p;
471         for (i = 0; i < req->pipeline_enable.n_tables; i++)
472                 p->table_data[i].a =
473                         req->pipeline_enable.table[i].a;
474
475         p->n_tables = req->pipeline_enable.n_tables;
476
477         p->msgq_req = req->pipeline_enable.msgq_req;
478         p->msgq_rsp = req->pipeline_enable.msgq_rsp;
479         p->timer_period =
480                 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
481         p->time_next = rte_get_tsc_cycles() + p->timer_period;
482
483         t->n_pipelines++;
484
485         /* Response */
486         rsp->status = 0;
487         return rsp;
488 }
489
490 static struct thread_msg_rsp *
491 thread_msg_handle_pipeline_disable(struct thread_data *t,
492         struct thread_msg_req *req)
493 {
494         struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req;
495         uint32_t n_pipelines = t->n_pipelines;
496         struct rte_pipeline *pipeline = req->pipeline_disable.p;
497         uint32_t i;
498
499         /* find pipeline */
500         for (i = 0; i < n_pipelines; i++) {
501                 struct pipeline_data *p = &t->pipeline_data[i];
502
503                 if (p->p != pipeline)
504                         continue;
505
506                 if (i < n_pipelines - 1) {
507                         struct rte_pipeline *pipeline_last =
508                                 t->p[n_pipelines - 1];
509                         struct pipeline_data *p_last =
510                                 &t->pipeline_data[n_pipelines - 1];
511
512                         t->p[i] = pipeline_last;
513                         memcpy(p, p_last, sizeof(*p));
514                 }
515
516                 t->n_pipelines--;
517
518                 rsp->status = 0;
519                 return rsp;
520         }
521
522         /* should not get here */
523         rsp->status = 0;
524         return rsp;
525 }
526
527 static void
528 thread_msg_handle(struct thread_data *t)
529 {
530         for ( ; ; ) {
531                 struct thread_msg_req *req;
532                 struct thread_msg_rsp *rsp;
533
534                 req = thread_msg_recv(t->msgq_req);
535                 if (req == NULL)
536                         break;
537
538                 switch (req->type) {
539                 case THREAD_REQ_PIPELINE_ENABLE:
540                         rsp = thread_msg_handle_pipeline_enable(t, req);
541                         break;
542
543                 case THREAD_REQ_PIPELINE_DISABLE:
544                         rsp = thread_msg_handle_pipeline_disable(t, req);
545                         break;
546
547                 default:
548                         rsp = (struct thread_msg_rsp *) req;
549                         rsp->status = -1;
550                 }
551
552                 thread_msg_send(t->msgq_rsp, rsp);
553         }
554 }
555
556 /**
557  * Main thread & data plane threads: message passing
558  */
559 enum pipeline_req_type {
560         /* Port IN */
561         PIPELINE_REQ_PORT_IN_STATS_READ,
562         PIPELINE_REQ_PORT_IN_ENABLE,
563         PIPELINE_REQ_PORT_IN_DISABLE,
564
565         /* Port OUT */
566         PIPELINE_REQ_PORT_OUT_STATS_READ,
567
568         /* Table */
569         PIPELINE_REQ_TABLE_STATS_READ,
570         PIPELINE_REQ_TABLE_RULE_ADD,
571         PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
572         PIPELINE_REQ_TABLE_RULE_ADD_BULK,
573         PIPELINE_REQ_TABLE_RULE_DELETE,
574         PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
575         PIPELINE_REQ_TABLE_RULE_STATS_READ,
576         PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
577         PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
578         PIPELINE_REQ_TABLE_RULE_MTR_READ,
579         PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
580         PIPELINE_REQ_TABLE_RULE_TTL_READ,
581         PIPELINE_REQ_TABLE_RULE_TIME_READ,
582         PIPELINE_REQ_MAX
583 };
584
585 struct pipeline_msg_req_port_in_stats_read {
586         int clear;
587 };
588
589 struct pipeline_msg_req_port_out_stats_read {
590         int clear;
591 };
592
593 struct pipeline_msg_req_table_stats_read {
594         int clear;
595 };
596
597 struct pipeline_msg_req_table_rule_add {
598         struct table_rule_match match;
599         struct table_rule_action action;
600 };
601
602 struct pipeline_msg_req_table_rule_add_default {
603         struct table_rule_action action;
604 };
605
606 struct pipeline_msg_req_table_rule_add_bulk {
607         struct table_rule_list *list;
608         int bulk;
609 };
610
611 struct pipeline_msg_req_table_rule_delete {
612         struct table_rule_match match;
613 };
614
615 struct pipeline_msg_req_table_rule_stats_read {
616         void *data;
617         int clear;
618 };
619
620 struct pipeline_msg_req_table_mtr_profile_add {
621         uint32_t meter_profile_id;
622         struct rte_table_action_meter_profile profile;
623 };
624
625 struct pipeline_msg_req_table_mtr_profile_delete {
626         uint32_t meter_profile_id;
627 };
628
629 struct pipeline_msg_req_table_rule_mtr_read {
630         void *data;
631         uint32_t tc_mask;
632         int clear;
633 };
634
635 struct pipeline_msg_req_table_dscp_table_update {
636         uint64_t dscp_mask;
637         struct rte_table_action_dscp_table dscp_table;
638 };
639
640 struct pipeline_msg_req_table_rule_ttl_read {
641         void *data;
642         int clear;
643 };
644
645 struct pipeline_msg_req_table_rule_time_read {
646         void *data;
647 };
648
649 struct pipeline_msg_req {
650         enum pipeline_req_type type;
651         uint32_t id; /* Port IN, port OUT or table ID */
652
653         RTE_STD_C11
654         union {
655                 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
656                 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
657                 struct pipeline_msg_req_table_stats_read table_stats_read;
658                 struct pipeline_msg_req_table_rule_add table_rule_add;
659                 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
660                 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
661                 struct pipeline_msg_req_table_rule_delete table_rule_delete;
662                 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
663                 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
664                 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
665                 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
666                 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
667                 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
668                 struct pipeline_msg_req_table_rule_time_read table_rule_time_read;
669         };
670 };
671
672 struct pipeline_msg_rsp_port_in_stats_read {
673         struct rte_pipeline_port_in_stats stats;
674 };
675
676 struct pipeline_msg_rsp_port_out_stats_read {
677         struct rte_pipeline_port_out_stats stats;
678 };
679
680 struct pipeline_msg_rsp_table_stats_read {
681         struct rte_pipeline_table_stats stats;
682 };
683
684 struct pipeline_msg_rsp_table_rule_add {
685         void *data;
686 };
687
688 struct pipeline_msg_rsp_table_rule_add_default {
689         void *data;
690 };
691
692 struct pipeline_msg_rsp_table_rule_add_bulk {
693         uint32_t n_rules;
694 };
695
696 struct pipeline_msg_rsp_table_rule_stats_read {
697         struct rte_table_action_stats_counters stats;
698 };
699
700 struct pipeline_msg_rsp_table_rule_mtr_read {
701         struct rte_table_action_mtr_counters stats;
702 };
703
704 struct pipeline_msg_rsp_table_rule_ttl_read {
705         struct rte_table_action_ttl_counters stats;
706 };
707
708 struct pipeline_msg_rsp_table_rule_time_read {
709         uint64_t timestamp;
710 };
711
712 struct pipeline_msg_rsp {
713         int status;
714
715         RTE_STD_C11
716         union {
717                 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
718                 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
719                 struct pipeline_msg_rsp_table_stats_read table_stats_read;
720                 struct pipeline_msg_rsp_table_rule_add table_rule_add;
721                 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
722                 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
723                 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
724                 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
725                 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
726                 struct pipeline_msg_rsp_table_rule_time_read table_rule_time_read;
727         };
728 };
729
730 /**
731  * Main thread
732  */
733 static struct pipeline_msg_req *
734 pipeline_msg_alloc(void)
735 {
736         size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
737                 sizeof(struct pipeline_msg_rsp));
738
739         return calloc(1, size);
740 }
741
742 static void
743 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
744 {
745         free(rsp);
746 }
747
748 static struct pipeline_msg_rsp *
749 pipeline_msg_send_recv(struct pipeline *p,
750         struct pipeline_msg_req *req)
751 {
752         struct rte_ring *msgq_req = p->msgq_req;
753         struct rte_ring *msgq_rsp = p->msgq_rsp;
754         struct pipeline_msg_rsp *rsp;
755         int status;
756
757         /* send */
758         do {
759                 status = rte_ring_sp_enqueue(msgq_req, req);
760         } while (status == -ENOBUFS);
761
762         /* recv */
763         do {
764                 status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp);
765         } while (status != 0);
766
767         return rsp;
768 }
769
770 int
771 pipeline_port_in_stats_read(const char *pipeline_name,
772         uint32_t port_id,
773         struct rte_pipeline_port_in_stats *stats,
774         int clear)
775 {
776         struct pipeline *p;
777         struct pipeline_msg_req *req;
778         struct pipeline_msg_rsp *rsp;
779         int status;
780
781         /* Check input params */
782         if ((pipeline_name == NULL) ||
783                 (stats == NULL))
784                 return -1;
785
786         p = pipeline_find(pipeline_name);
787         if ((p == NULL) ||
788                 (port_id >= p->n_ports_in))
789                 return -1;
790
791         if (!pipeline_is_running(p)) {
792                 status = rte_pipeline_port_in_stats_read(p->p,
793                         port_id,
794                         stats,
795                         clear);
796
797                 return status;
798         }
799
800         /* Allocate request */
801         req = pipeline_msg_alloc();
802         if (req == NULL)
803                 return -1;
804
805         /* Write request */
806         req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
807         req->id = port_id;
808         req->port_in_stats_read.clear = clear;
809
810         /* Send request and wait for response */
811         rsp = pipeline_msg_send_recv(p, req);
812
813         /* Read response */
814         status = rsp->status;
815         if (status == 0)
816                 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
817
818         /* Free response */
819         pipeline_msg_free(rsp);
820
821         return status;
822 }
823
824 int
825 pipeline_port_in_enable(const char *pipeline_name,
826         uint32_t port_id)
827 {
828         struct pipeline *p;
829         struct pipeline_msg_req *req;
830         struct pipeline_msg_rsp *rsp;
831         int status;
832
833         /* Check input params */
834         if (pipeline_name == NULL)
835                 return -1;
836
837         p = pipeline_find(pipeline_name);
838         if ((p == NULL) ||
839                 (port_id >= p->n_ports_in))
840                 return -1;
841
842         if (!pipeline_is_running(p)) {
843                 status = rte_pipeline_port_in_enable(p->p, port_id);
844                 return status;
845         }
846
847         /* Allocate request */
848         req = pipeline_msg_alloc();
849         if (req == NULL)
850                 return -1;
851
852         /* Write request */
853         req->type = PIPELINE_REQ_PORT_IN_ENABLE;
854         req->id = port_id;
855
856         /* Send request and wait for response */
857         rsp = pipeline_msg_send_recv(p, req);
858
859         /* Read response */
860         status = rsp->status;
861
862         /* Free response */
863         pipeline_msg_free(rsp);
864
865         return status;
866 }
867
868 int
869 pipeline_port_in_disable(const char *pipeline_name,
870         uint32_t port_id)
871 {
872         struct pipeline *p;
873         struct pipeline_msg_req *req;
874         struct pipeline_msg_rsp *rsp;
875         int status;
876
877         /* Check input params */
878         if (pipeline_name == NULL)
879                 return -1;
880
881         p = pipeline_find(pipeline_name);
882         if ((p == NULL) ||
883                 (port_id >= p->n_ports_in))
884                 return -1;
885
886         if (!pipeline_is_running(p)) {
887                 status = rte_pipeline_port_in_disable(p->p, port_id);
888                 return status;
889         }
890
891         /* Allocate request */
892         req = pipeline_msg_alloc();
893         if (req == NULL)
894                 return -1;
895
896         /* Write request */
897         req->type = PIPELINE_REQ_PORT_IN_DISABLE;
898         req->id = port_id;
899
900         /* Send request and wait for response */
901         rsp = pipeline_msg_send_recv(p, req);
902
903         /* Read response */
904         status = rsp->status;
905
906         /* Free response */
907         pipeline_msg_free(rsp);
908
909         return status;
910 }
911
912 int
913 pipeline_port_out_stats_read(const char *pipeline_name,
914         uint32_t port_id,
915         struct rte_pipeline_port_out_stats *stats,
916         int clear)
917 {
918         struct pipeline *p;
919         struct pipeline_msg_req *req;
920         struct pipeline_msg_rsp *rsp;
921         int status;
922
923         /* Check input params */
924         if ((pipeline_name == NULL) ||
925                 (stats == NULL))
926                 return -1;
927
928         p = pipeline_find(pipeline_name);
929         if ((p == NULL) ||
930                 (port_id >= p->n_ports_out))
931                 return -1;
932
933         if (!pipeline_is_running(p)) {
934                 status = rte_pipeline_port_out_stats_read(p->p,
935                         port_id,
936                         stats,
937                         clear);
938
939                 return status;
940         }
941
942         /* Allocate request */
943         req = pipeline_msg_alloc();
944         if (req == NULL)
945                 return -1;
946
947         /* Write request */
948         req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
949         req->id = port_id;
950         req->port_out_stats_read.clear = clear;
951
952         /* Send request and wait for response */
953         rsp = pipeline_msg_send_recv(p, req);
954
955         /* Read response */
956         status = rsp->status;
957         if (status == 0)
958                 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
959
960         /* Free response */
961         pipeline_msg_free(rsp);
962
963         return status;
964 }
965
966 int
967 pipeline_table_stats_read(const char *pipeline_name,
968         uint32_t table_id,
969         struct rte_pipeline_table_stats *stats,
970         int clear)
971 {
972         struct pipeline *p;
973         struct pipeline_msg_req *req;
974         struct pipeline_msg_rsp *rsp;
975         int status;
976
977         /* Check input params */
978         if ((pipeline_name == NULL) ||
979                 (stats == NULL))
980                 return -1;
981
982         p = pipeline_find(pipeline_name);
983         if ((p == NULL) ||
984                 (table_id >= p->n_tables))
985                 return -1;
986
987         if (!pipeline_is_running(p)) {
988                 status = rte_pipeline_table_stats_read(p->p,
989                         table_id,
990                         stats,
991                         clear);
992
993                 return status;
994         }
995
996         /* Allocate request */
997         req = pipeline_msg_alloc();
998         if (req == NULL)
999                 return -1;
1000
1001         /* Write request */
1002         req->type = PIPELINE_REQ_TABLE_STATS_READ;
1003         req->id = table_id;
1004         req->table_stats_read.clear = clear;
1005
1006         /* Send request and wait for response */
1007         rsp = pipeline_msg_send_recv(p, req);
1008
1009         /* Read response */
1010         status = rsp->status;
1011         if (status == 0)
1012                 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
1013
1014         /* Free response */
1015         pipeline_msg_free(rsp);
1016
1017         return status;
1018 }
1019
1020 static int
1021 match_check(struct table_rule_match *match,
1022         struct pipeline *p,
1023         uint32_t table_id)
1024 {
1025         struct table *table;
1026
1027         if ((match == NULL) ||
1028                 (p == NULL) ||
1029                 (table_id >= p->n_tables))
1030                 return -1;
1031
1032         table = &p->table[table_id];
1033         if (match->match_type != table->params.match_type)
1034                 return -1;
1035
1036         switch (match->match_type) {
1037         case TABLE_ACL:
1038         {
1039                 struct table_acl_params *t = &table->params.match.acl;
1040                 struct table_rule_match_acl *r = &match->match.acl;
1041
1042                 if ((r->ip_version && (t->ip_version == 0)) ||
1043                         ((r->ip_version == 0) && t->ip_version))
1044                         return -1;
1045
1046                 if (r->ip_version) {
1047                         if ((r->sa_depth > 32) ||
1048                                 (r->da_depth > 32))
1049                                 return -1;
1050                 } else {
1051                         if ((r->sa_depth > 128) ||
1052                                 (r->da_depth > 128))
1053                                 return -1;
1054                 }
1055                 return 0;
1056         }
1057
1058         case TABLE_ARRAY:
1059                 return 0;
1060
1061         case TABLE_HASH:
1062                 return 0;
1063
1064         case TABLE_LPM:
1065         {
1066                 struct table_lpm_params *t = &table->params.match.lpm;
1067                 struct table_rule_match_lpm *r = &match->match.lpm;
1068
1069                 if ((r->ip_version && (t->key_size != 4)) ||
1070                         ((r->ip_version == 0) && (t->key_size != 16)))
1071                         return -1;
1072
1073                 if (r->ip_version) {
1074                         if (r->depth > 32)
1075                                 return -1;
1076                 } else {
1077                         if (r->depth > 128)
1078                                 return -1;
1079                 }
1080                 return 0;
1081         }
1082
1083         case TABLE_STUB:
1084                 return -1;
1085
1086         default:
1087                 return -1;
1088         }
1089 }
1090
1091 static int
1092 action_check(struct table_rule_action *action,
1093         struct pipeline *p,
1094         uint32_t table_id)
1095 {
1096         struct table_action_profile *ap;
1097
1098         if ((action == NULL) ||
1099                 (p == NULL) ||
1100                 (table_id >= p->n_tables))
1101                 return -1;
1102
1103         ap = p->table[table_id].ap;
1104         if (action->action_mask != ap->params.action_mask)
1105                 return -1;
1106
1107         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1108                 if ((action->fwd.action == RTE_PIPELINE_ACTION_PORT) &&
1109                         (action->fwd.id >= p->n_ports_out))
1110                         return -1;
1111
1112                 if ((action->fwd.action == RTE_PIPELINE_ACTION_TABLE) &&
1113                         (action->fwd.id >= p->n_tables))
1114                         return -1;
1115         }
1116
1117         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1118                 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1119                 uint32_t tc_mask1 = action->mtr.tc_mask;
1120
1121                 if (tc_mask1 != tc_mask0)
1122                         return -1;
1123         }
1124
1125         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1126                 uint32_t n_subports_per_port =
1127                         ap->params.tm.n_subports_per_port;
1128                 uint32_t n_pipes_per_subport =
1129                         ap->params.tm.n_pipes_per_subport;
1130                 uint32_t subport_id = action->tm.subport_id;
1131                 uint32_t pipe_id = action->tm.pipe_id;
1132
1133                 if ((subport_id >= n_subports_per_port) ||
1134                         (pipe_id >= n_pipes_per_subport))
1135                         return -1;
1136         }
1137
1138         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1139                 uint64_t encap_mask = ap->params.encap.encap_mask;
1140                 enum rte_table_action_encap_type type = action->encap.type;
1141
1142                 if ((encap_mask & (1LLU << type)) == 0)
1143                         return -1;
1144         }
1145
1146         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1147                 int ip_version0 = ap->params.common.ip_version;
1148                 int ip_version1 = action->nat.ip_version;
1149
1150                 if ((ip_version1 && (ip_version0 == 0)) ||
1151                         ((ip_version1 == 0) && ip_version0))
1152                         return -1;
1153         }
1154
1155         return 0;
1156 }
1157
1158 static int
1159 action_default_check(struct table_rule_action *action,
1160         struct pipeline *p,
1161         uint32_t table_id)
1162 {
1163         if ((action == NULL) ||
1164                 (action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD)) ||
1165                 (p == NULL) ||
1166                 (table_id >= p->n_tables))
1167                 return -1;
1168
1169         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1170                 if ((action->fwd.action == RTE_PIPELINE_ACTION_PORT) &&
1171                         (action->fwd.id >= p->n_ports_out))
1172                         return -1;
1173
1174                 if ((action->fwd.action == RTE_PIPELINE_ACTION_TABLE) &&
1175                         (action->fwd.id >= p->n_tables))
1176                         return -1;
1177         }
1178
1179         return 0;
1180 }
1181
1182 union table_rule_match_low_level {
1183         struct rte_table_acl_rule_add_params acl_add;
1184         struct rte_table_acl_rule_delete_params acl_delete;
1185         struct rte_table_array_key array;
1186         uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1187         struct rte_table_lpm_key lpm_ipv4;
1188         struct rte_table_lpm_ipv6_key lpm_ipv6;
1189 };
1190
1191 static int
1192 match_convert(struct table_rule_match *mh,
1193         union table_rule_match_low_level *ml,
1194         int add);
1195
1196 static int
1197 action_convert(struct rte_table_action *a,
1198         struct table_rule_action *action,
1199         struct rte_pipeline_table_entry *data);
1200
1201 struct table_ll {
1202         struct rte_pipeline *p;
1203         int table_id;
1204         struct rte_table_action *a;
1205         int bulk_supported;
1206 };
1207
1208 static int
1209 table_rule_add_bulk_ll(struct table_ll *table,
1210         struct table_rule_list *list,
1211         uint32_t *n_rules)
1212 {
1213         union table_rule_match_low_level *match_ll = NULL;
1214         uint8_t *action_ll = NULL;
1215         void **match_ll_ptr = NULL;
1216         struct rte_pipeline_table_entry **action_ll_ptr = NULL;
1217         struct rte_pipeline_table_entry **entries_ptr = NULL;
1218         int *found = NULL;
1219         struct table_rule *rule;
1220         uint32_t n, i;
1221         int status = 0;
1222
1223         n = 0;
1224         TAILQ_FOREACH(rule, list, node)
1225                 n++;
1226
1227         /* Memory allocation */
1228         match_ll = calloc(n, sizeof(union table_rule_match_low_level));
1229         action_ll = calloc(n, TABLE_RULE_ACTION_SIZE_MAX);
1230
1231         match_ll_ptr = calloc(n, sizeof(void *));
1232         action_ll_ptr = calloc(n, sizeof(struct rte_pipeline_table_entry *));
1233
1234         entries_ptr = calloc(n, sizeof(struct rte_pipeline_table_entry *));
1235         found = calloc(n, sizeof(int));
1236
1237         if (match_ll == NULL ||
1238                 action_ll == NULL ||
1239                 match_ll_ptr == NULL ||
1240                 action_ll_ptr == NULL ||
1241                 entries_ptr == NULL ||
1242                 found == NULL) {
1243                         status = -ENOMEM;
1244                         goto table_rule_add_bulk_ll_free;
1245         }
1246
1247         /* Init */
1248         for (i = 0; i < n; i++) {
1249                 match_ll_ptr[i] = (void *)&match_ll[i];
1250                 action_ll_ptr[i] = (struct rte_pipeline_table_entry *)
1251                         &action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1252         }
1253
1254         /* Rule (match, action) conversion */
1255         i = 0;
1256         TAILQ_FOREACH(rule, list, node) {
1257                 status = match_convert(&rule->match, match_ll_ptr[i], 1);
1258                 if (status)
1259                         goto table_rule_add_bulk_ll_free;
1260
1261                 status = action_convert(table->a, &rule->action, action_ll_ptr[i]);
1262                 if (status)
1263                         goto table_rule_add_bulk_ll_free;
1264
1265                 i++;
1266         }
1267
1268         /* Add rule (match, action) to table */
1269         if (table->bulk_supported) {
1270                 status = rte_pipeline_table_entry_add_bulk(table->p,
1271                         table->table_id,
1272                         match_ll_ptr,
1273                         action_ll_ptr,
1274                         n,
1275                         found,
1276                         entries_ptr);
1277                 if (status)
1278                         goto table_rule_add_bulk_ll_free;
1279         } else
1280                 for (i = 0; i < n; i++) {
1281                         status = rte_pipeline_table_entry_add(table->p,
1282                                 table->table_id,
1283                                 match_ll_ptr[i],
1284                                 action_ll_ptr[i],
1285                                 &found[i],
1286                                 &entries_ptr[i]);
1287                         if (status) {
1288                                 if (i == 0)
1289                                         goto table_rule_add_bulk_ll_free;
1290
1291                                 /* No roll-back. */
1292                                 status = 0;
1293                                 n = i;
1294                                 break;
1295                         }
1296                 }
1297
1298         /* Write back to the rule list. */
1299         i = 0;
1300         TAILQ_FOREACH(rule, list, node) {
1301                 if (i >= n)
1302                         break;
1303
1304                 rule->data = entries_ptr[i];
1305
1306                 i++;
1307         }
1308
1309         *n_rules = n;
1310
1311         /* Free */
1312 table_rule_add_bulk_ll_free:
1313         free(found);
1314         free(entries_ptr);
1315         free(action_ll_ptr);
1316         free(match_ll_ptr);
1317         free(action_ll);
1318         free(match_ll);
1319
1320         return status;
1321 }
1322
1323 int
1324 pipeline_table_rule_add(const char *pipeline_name,
1325         uint32_t table_id,
1326         struct table_rule_match *match,
1327         struct table_rule_action *action)
1328 {
1329         struct pipeline *p;
1330         struct table *table;
1331         struct pipeline_msg_req *req;
1332         struct pipeline_msg_rsp *rsp;
1333         struct table_rule *rule;
1334         int status;
1335
1336         /* Check input params */
1337         if ((pipeline_name == NULL) ||
1338                 (match == NULL) ||
1339                 (action == NULL))
1340                 return -1;
1341
1342         p = pipeline_find(pipeline_name);
1343         if ((p == NULL) ||
1344                 (table_id >= p->n_tables) ||
1345                 match_check(match, p, table_id) ||
1346                 action_check(action, p, table_id))
1347                 return -1;
1348
1349         table = &p->table[table_id];
1350
1351         rule = calloc(1, sizeof(struct table_rule));
1352         if (rule == NULL)
1353                 return -1;
1354
1355         memcpy(&rule->match, match, sizeof(*match));
1356         memcpy(&rule->action, action, sizeof(*action));
1357
1358         if (!pipeline_is_running(p)) {
1359                 union table_rule_match_low_level match_ll;
1360                 struct rte_pipeline_table_entry *data_in, *data_out;
1361                 int key_found;
1362                 uint8_t *buffer;
1363
1364                 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1365                 if (buffer == NULL) {
1366                         free(rule);
1367                         return -1;
1368                 }
1369
1370                 /* Table match-action rule conversion */
1371                 data_in = (struct rte_pipeline_table_entry *)buffer;
1372
1373                 status = match_convert(match, &match_ll, 1);
1374                 if (status) {
1375                         free(buffer);
1376                         free(rule);
1377                         return -1;
1378                 }
1379
1380                 status = action_convert(table->a, action, data_in);
1381                 if (status) {
1382                         free(buffer);
1383                         free(rule);
1384                         return -1;
1385                 }
1386
1387                 /* Add rule (match, action) to table */
1388                 status = rte_pipeline_table_entry_add(p->p,
1389                                 table_id,
1390                                 &match_ll,
1391                                 data_in,
1392                                 &key_found,
1393                                 &data_out);
1394                 if (status) {
1395                         free(buffer);
1396                         free(rule);
1397                         return -1;
1398                 }
1399
1400                 /* Write Response */
1401                 rule->data = data_out;
1402                 table_rule_add(table, rule);
1403
1404                 free(buffer);
1405                 return 0;
1406         }
1407
1408         /* Allocate request */
1409         req = pipeline_msg_alloc();
1410         if (req == NULL) {
1411                 free(rule);
1412                 return -1;
1413         }
1414
1415         /* Write request */
1416         req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1417         req->id = table_id;
1418         memcpy(&req->table_rule_add.match, match, sizeof(*match));
1419         memcpy(&req->table_rule_add.action, action, sizeof(*action));
1420
1421         /* Send request and wait for response */
1422         rsp = pipeline_msg_send_recv(p, req);
1423
1424         /* Read response */
1425         status = rsp->status;
1426         if (status == 0) {
1427                 rule->data = rsp->table_rule_add.data;
1428                 table_rule_add(table, rule);
1429         } else
1430                 free(rule);
1431
1432         /* Free response */
1433         pipeline_msg_free(rsp);
1434
1435         return status;
1436 }
1437
1438 int
1439 pipeline_table_rule_add_default(const char *pipeline_name,
1440         uint32_t table_id,
1441         struct table_rule_action *action)
1442 {
1443         struct pipeline *p;
1444         struct table *table;
1445         struct pipeline_msg_req *req;
1446         struct pipeline_msg_rsp *rsp;
1447         struct table_rule *rule;
1448         int status;
1449
1450         /* Check input params */
1451         if ((pipeline_name == NULL) ||
1452                 (action == NULL))
1453                 return -1;
1454
1455         p = pipeline_find(pipeline_name);
1456         if ((p == NULL) ||
1457                 (table_id >= p->n_tables) ||
1458                 action_default_check(action, p, table_id))
1459                 return -1;
1460
1461         table = &p->table[table_id];
1462
1463         rule = calloc(1, sizeof(struct table_rule));
1464         if (rule == NULL)
1465                 return -1;
1466
1467         memcpy(&rule->action, action, sizeof(*action));
1468
1469         if (!pipeline_is_running(p)) {
1470                 struct rte_pipeline_table_entry *data_in, *data_out;
1471                 uint8_t *buffer;
1472
1473                 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1474                 if (buffer == NULL) {
1475                         free(rule);
1476                         return -1;
1477                 }
1478
1479                 /* Apply actions */
1480                 data_in = (struct rte_pipeline_table_entry *)buffer;
1481
1482                 data_in->action = action->fwd.action;
1483                 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1484                         data_in->port_id = action->fwd.id;
1485                 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1486                         data_in->table_id = action->fwd.id;
1487
1488                 /* Add default rule to table */
1489                 status = rte_pipeline_table_default_entry_add(p->p,
1490                                 table_id,
1491                                 data_in,
1492                                 &data_out);
1493                 if (status) {
1494                         free(buffer);
1495                         free(rule);
1496                         return -1;
1497                 }
1498
1499                 /* Write Response */
1500                 rule->data = data_out;
1501                 table_rule_default_add(table, rule);
1502
1503                 free(buffer);
1504                 return 0;
1505         }
1506
1507         /* Allocate request */
1508         req = pipeline_msg_alloc();
1509         if (req == NULL) {
1510                 free(rule);
1511                 return -1;
1512         }
1513
1514         /* Write request */
1515         req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1516         req->id = table_id;
1517         memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1518
1519         /* Send request and wait for response */
1520         rsp = pipeline_msg_send_recv(p, req);
1521
1522         /* Read response */
1523         status = rsp->status;
1524         if (status == 0) {
1525                 rule->data = rsp->table_rule_add_default.data;
1526                 table_rule_default_add(table, rule);
1527         } else
1528                 free(rule);
1529
1530         /* Free response */
1531         pipeline_msg_free(rsp);
1532
1533         return status;
1534 }
1535
1536 static uint32_t
1537 table_rule_list_free(struct table_rule_list *list)
1538 {
1539         uint32_t n = 0;
1540
1541         if (!list)
1542                 return 0;
1543
1544         for ( ; ; ) {
1545                 struct table_rule *rule;
1546
1547                 rule = TAILQ_FIRST(list);
1548                 if (rule == NULL)
1549                         break;
1550
1551                 TAILQ_REMOVE(list, rule, node);
1552                 free(rule);
1553                 n++;
1554         }
1555
1556         free(list);
1557         return n;
1558 }
1559
1560 int
1561 pipeline_table_rule_add_bulk(const char *pipeline_name,
1562         uint32_t table_id,
1563         struct table_rule_list *list,
1564         uint32_t *n_rules_added,
1565         uint32_t *n_rules_not_added)
1566 {
1567         struct pipeline *p;
1568         struct table *table;
1569         struct pipeline_msg_req *req;
1570         struct pipeline_msg_rsp *rsp;
1571         struct table_rule *rule;
1572         int status = 0;
1573
1574         /* Check input params */
1575         if ((pipeline_name == NULL) ||
1576                 (list == NULL) ||
1577                 TAILQ_EMPTY(list) ||
1578                 (n_rules_added == NULL) ||
1579                 (n_rules_not_added == NULL)) {
1580                 table_rule_list_free(list);
1581                 return -EINVAL;
1582         }
1583
1584         p = pipeline_find(pipeline_name);
1585         if ((p == NULL) ||
1586                 (table_id >= p->n_tables)) {
1587                 table_rule_list_free(list);
1588                 return -EINVAL;
1589         }
1590
1591         table = &p->table[table_id];
1592
1593         TAILQ_FOREACH(rule, list, node)
1594                 if (match_check(&rule->match, p, table_id) ||
1595                         action_check(&rule->action, p, table_id)) {
1596                         table_rule_list_free(list);
1597                         return -EINVAL;
1598                 }
1599
1600         if (!pipeline_is_running(p)) {
1601                 struct table_ll table_ll = {
1602                         .p = p->p,
1603                         .table_id = table_id,
1604                         .a = table->a,
1605                         .bulk_supported = table->params.match_type == TABLE_ACL,
1606                 };
1607
1608                 status = table_rule_add_bulk_ll(&table_ll, list, n_rules_added);
1609                 if (status) {
1610                         table_rule_list_free(list);
1611                         return status;
1612                 }
1613
1614                 table_rule_add_bulk(table, list, *n_rules_added);
1615                 *n_rules_not_added = table_rule_list_free(list);
1616                 return 0;
1617         }
1618
1619         /* Allocate request */
1620         req = pipeline_msg_alloc();
1621         if (req == NULL) {
1622                 table_rule_list_free(list);
1623                 return -ENOMEM;
1624         }
1625
1626         /* Write request */
1627         req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1628         req->id = table_id;
1629         req->table_rule_add_bulk.list = list;
1630         req->table_rule_add_bulk.bulk = table->params.match_type == TABLE_ACL;
1631
1632         /* Send request and wait for response */
1633         rsp = pipeline_msg_send_recv(p, req);
1634
1635         /* Read response */
1636         status = rsp->status;
1637         if (status == 0) {
1638                 *n_rules_added = rsp->table_rule_add_bulk.n_rules;
1639
1640                 table_rule_add_bulk(table, list, *n_rules_added);
1641                 *n_rules_not_added = table_rule_list_free(list);
1642         } else
1643                 table_rule_list_free(list);
1644
1645
1646         /* Free response */
1647         pipeline_msg_free(rsp);
1648
1649         return status;
1650 }
1651
1652 int
1653 pipeline_table_rule_delete(const char *pipeline_name,
1654         uint32_t table_id,
1655         struct table_rule_match *match)
1656 {
1657         struct pipeline *p;
1658         struct table *table;
1659         struct pipeline_msg_req *req;
1660         struct pipeline_msg_rsp *rsp;
1661         int status;
1662
1663         /* Check input params */
1664         if ((pipeline_name == NULL) ||
1665                 (match == NULL))
1666                 return -1;
1667
1668         p = pipeline_find(pipeline_name);
1669         if ((p == NULL) ||
1670                 (table_id >= p->n_tables) ||
1671                 match_check(match, p, table_id))
1672                 return -1;
1673
1674         table = &p->table[table_id];
1675
1676         if (!pipeline_is_running(p)) {
1677                 union table_rule_match_low_level match_ll;
1678                 int key_found;
1679
1680                 status = match_convert(match, &match_ll, 0);
1681                 if (status)
1682                         return -1;
1683
1684                 status = rte_pipeline_table_entry_delete(p->p,
1685                                 table_id,
1686                                 &match_ll,
1687                                 &key_found,
1688                                 NULL);
1689
1690                 if (status == 0)
1691                         table_rule_delete(table, match);
1692
1693                 return status;
1694         }
1695
1696         /* Allocate request */
1697         req = pipeline_msg_alloc();
1698         if (req == NULL)
1699                 return -1;
1700
1701         /* Write request */
1702         req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1703         req->id = table_id;
1704         memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1705
1706         /* Send request and wait for response */
1707         rsp = pipeline_msg_send_recv(p, req);
1708
1709         /* Read response */
1710         status = rsp->status;
1711         if (status == 0)
1712                 table_rule_delete(table, match);
1713
1714         /* Free response */
1715         pipeline_msg_free(rsp);
1716
1717         return status;
1718 }
1719
1720 int
1721 pipeline_table_rule_delete_default(const char *pipeline_name,
1722         uint32_t table_id)
1723 {
1724         struct pipeline *p;
1725         struct table *table;
1726         struct pipeline_msg_req *req;
1727         struct pipeline_msg_rsp *rsp;
1728         int status;
1729
1730         /* Check input params */
1731         if (pipeline_name == NULL)
1732                 return -1;
1733
1734         p = pipeline_find(pipeline_name);
1735         if ((p == NULL) ||
1736                 (table_id >= p->n_tables))
1737                 return -1;
1738
1739         table = &p->table[table_id];
1740
1741         if (!pipeline_is_running(p)) {
1742                 status = rte_pipeline_table_default_entry_delete(p->p,
1743                         table_id,
1744                         NULL);
1745
1746                 if (status == 0)
1747                         table_rule_default_delete(table);
1748
1749                 return status;
1750         }
1751
1752         /* Allocate request */
1753         req = pipeline_msg_alloc();
1754         if (req == NULL)
1755                 return -1;
1756
1757         /* Write request */
1758         req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1759         req->id = table_id;
1760
1761         /* Send request and wait for response */
1762         rsp = pipeline_msg_send_recv(p, req);
1763
1764         /* Read response */
1765         status = rsp->status;
1766         if (status == 0)
1767                 table_rule_default_delete(table);
1768
1769         /* Free response */
1770         pipeline_msg_free(rsp);
1771
1772         return status;
1773 }
1774
1775 int
1776 pipeline_table_rule_stats_read(const char *pipeline_name,
1777         uint32_t table_id,
1778         struct table_rule_match *match,
1779         struct rte_table_action_stats_counters *stats,
1780         int clear)
1781 {
1782         struct pipeline *p;
1783         struct table *table;
1784         struct pipeline_msg_req *req;
1785         struct pipeline_msg_rsp *rsp;
1786         struct table_rule *rule;
1787         int status;
1788
1789         /* Check input params */
1790         if ((pipeline_name == NULL) ||
1791                 (match == NULL) ||
1792                 (stats == NULL))
1793                 return -1;
1794
1795         p = pipeline_find(pipeline_name);
1796         if ((p == NULL) ||
1797                 (table_id >= p->n_tables) ||
1798                 match_check(match, p, table_id))
1799                 return -1;
1800
1801         table = &p->table[table_id];
1802         rule = table_rule_find(table, match);
1803         if (rule == NULL)
1804                 return -1;
1805
1806         if (!pipeline_is_running(p)) {
1807                 status = rte_table_action_stats_read(table->a,
1808                         rule->data,
1809                         stats,
1810                         clear);
1811
1812                 return status;
1813         }
1814
1815         /* Allocate request */
1816         req = pipeline_msg_alloc();
1817         if (req == NULL)
1818                 return -1;
1819
1820         /* Write request */
1821         req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1822         req->id = table_id;
1823         req->table_rule_stats_read.data = rule->data;
1824         req->table_rule_stats_read.clear = clear;
1825
1826         /* Send request and wait for response */
1827         rsp = pipeline_msg_send_recv(p, req);
1828
1829         /* Read response */
1830         status = rsp->status;
1831         if (status == 0)
1832                 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1833
1834         /* Free response */
1835         pipeline_msg_free(rsp);
1836
1837         return status;
1838 }
1839
1840 int
1841 pipeline_table_mtr_profile_add(const char *pipeline_name,
1842         uint32_t table_id,
1843         uint32_t meter_profile_id,
1844         struct rte_table_action_meter_profile *profile)
1845 {
1846         struct pipeline *p;
1847         struct pipeline_msg_req *req;
1848         struct pipeline_msg_rsp *rsp;
1849         int status;
1850
1851         /* Check input params */
1852         if ((pipeline_name == NULL) ||
1853                 (profile == NULL))
1854                 return -1;
1855
1856         p = pipeline_find(pipeline_name);
1857         if ((p == NULL) ||
1858                 (table_id >= p->n_tables))
1859                 return -1;
1860
1861         if (!pipeline_is_running(p)) {
1862                 struct rte_table_action *a = p->table[table_id].a;
1863
1864                 status = rte_table_action_meter_profile_add(a,
1865                         meter_profile_id,
1866                         profile);
1867
1868                 return status;
1869         }
1870
1871         /* Allocate request */
1872         req = pipeline_msg_alloc();
1873         if (req == NULL)
1874                 return -1;
1875
1876         /* Write request */
1877         req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1878         req->id = table_id;
1879         req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1880         memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1881
1882         /* Send request and wait for response */
1883         rsp = pipeline_msg_send_recv(p, req);
1884
1885         /* Read response */
1886         status = rsp->status;
1887
1888         /* Free response */
1889         pipeline_msg_free(rsp);
1890
1891         return status;
1892 }
1893
1894 int
1895 pipeline_table_mtr_profile_delete(const char *pipeline_name,
1896         uint32_t table_id,
1897         uint32_t meter_profile_id)
1898 {
1899         struct pipeline *p;
1900         struct pipeline_msg_req *req;
1901         struct pipeline_msg_rsp *rsp;
1902         int status;
1903
1904         /* Check input params */
1905         if (pipeline_name == NULL)
1906                 return -1;
1907
1908         p = pipeline_find(pipeline_name);
1909         if ((p == NULL) ||
1910                 (table_id >= p->n_tables))
1911                 return -1;
1912
1913         if (!pipeline_is_running(p)) {
1914                 struct rte_table_action *a = p->table[table_id].a;
1915
1916                 status = rte_table_action_meter_profile_delete(a,
1917                                 meter_profile_id);
1918
1919                 return status;
1920         }
1921
1922         /* Allocate request */
1923         req = pipeline_msg_alloc();
1924         if (req == NULL)
1925                 return -1;
1926
1927         /* Write request */
1928         req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1929         req->id = table_id;
1930         req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1931
1932         /* Send request and wait for response */
1933         rsp = pipeline_msg_send_recv(p, req);
1934
1935         /* Read response */
1936         status = rsp->status;
1937
1938         /* Free response */
1939         pipeline_msg_free(rsp);
1940
1941         return status;
1942 }
1943
1944 int
1945 pipeline_table_rule_mtr_read(const char *pipeline_name,
1946         uint32_t table_id,
1947         struct table_rule_match *match,
1948         struct rte_table_action_mtr_counters *stats,
1949         int clear)
1950 {
1951         struct pipeline *p;
1952         struct table *table;
1953         struct pipeline_msg_req *req;
1954         struct pipeline_msg_rsp *rsp;
1955         struct table_rule *rule;
1956         uint32_t tc_mask;
1957         int status;
1958
1959         /* Check input params */
1960         if ((pipeline_name == NULL) ||
1961                 (match == NULL) ||
1962                 (stats == NULL))
1963                 return -1;
1964
1965         p = pipeline_find(pipeline_name);
1966         if ((p == NULL) ||
1967                 (table_id >= p->n_tables) ||
1968                 match_check(match, p, table_id))
1969                 return -1;
1970
1971         table = &p->table[table_id];
1972         tc_mask = (1 << table->ap->params.mtr.n_tc) - 1;
1973
1974         rule = table_rule_find(table, match);
1975         if (rule == NULL)
1976                 return -1;
1977
1978         if (!pipeline_is_running(p)) {
1979                 status = rte_table_action_meter_read(table->a,
1980                                 rule->data,
1981                                 tc_mask,
1982                                 stats,
1983                                 clear);
1984
1985                 return status;
1986         }
1987
1988         /* Allocate request */
1989         req = pipeline_msg_alloc();
1990         if (req == NULL)
1991                 return -1;
1992
1993         /* Write request */
1994         req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1995         req->id = table_id;
1996         req->table_rule_mtr_read.data = rule->data;
1997         req->table_rule_mtr_read.tc_mask = tc_mask;
1998         req->table_rule_mtr_read.clear = clear;
1999
2000         /* Send request and wait for response */
2001         rsp = pipeline_msg_send_recv(p, req);
2002
2003         /* Read response */
2004         status = rsp->status;
2005         if (status == 0)
2006                 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
2007
2008         /* Free response */
2009         pipeline_msg_free(rsp);
2010
2011         return status;
2012 }
2013
2014 int
2015 pipeline_table_dscp_table_update(const char *pipeline_name,
2016         uint32_t table_id,
2017         uint64_t dscp_mask,
2018         struct rte_table_action_dscp_table *dscp_table)
2019 {
2020         struct pipeline *p;
2021         struct pipeline_msg_req *req;
2022         struct pipeline_msg_rsp *rsp;
2023         int status;
2024
2025         /* Check input params */
2026         if ((pipeline_name == NULL) ||
2027                 (dscp_table == NULL))
2028                 return -1;
2029
2030         p = pipeline_find(pipeline_name);
2031         if ((p == NULL) ||
2032                 (table_id >= p->n_tables))
2033                 return -1;
2034
2035         if (!pipeline_is_running(p)) {
2036                 struct rte_table_action *a = p->table[table_id].a;
2037
2038                 status = rte_table_action_dscp_table_update(a,
2039                                 dscp_mask,
2040                                 dscp_table);
2041
2042                 return status;
2043         }
2044
2045         /* Allocate request */
2046         req = pipeline_msg_alloc();
2047         if (req == NULL)
2048                 return -1;
2049
2050         /* Write request */
2051         req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
2052         req->id = table_id;
2053         req->table_dscp_table_update.dscp_mask = dscp_mask;
2054         memcpy(&req->table_dscp_table_update.dscp_table,
2055                 dscp_table, sizeof(*dscp_table));
2056
2057         /* Send request and wait for response */
2058         rsp = pipeline_msg_send_recv(p, req);
2059
2060         /* Read response */
2061         status = rsp->status;
2062
2063         /* Free response */
2064         pipeline_msg_free(rsp);
2065
2066         return status;
2067 }
2068
2069 int
2070 pipeline_table_rule_ttl_read(const char *pipeline_name,
2071         uint32_t table_id,
2072         struct table_rule_match *match,
2073         struct rte_table_action_ttl_counters *stats,
2074         int clear)
2075 {
2076         struct pipeline *p;
2077         struct table *table;
2078         struct pipeline_msg_req *req;
2079         struct pipeline_msg_rsp *rsp;
2080         struct table_rule *rule;
2081         int status;
2082
2083         /* Check input params */
2084         if ((pipeline_name == NULL) ||
2085                 (match == NULL) ||
2086                 (stats == NULL))
2087                 return -1;
2088
2089         p = pipeline_find(pipeline_name);
2090         if ((p == NULL) ||
2091                 (table_id >= p->n_tables) ||
2092                 match_check(match, p, table_id))
2093                 return -1;
2094
2095         table = &p->table[table_id];
2096         if (!table->ap->params.ttl.n_packets_enabled)
2097                 return -1;
2098
2099         rule = table_rule_find(table, match);
2100         if (rule == NULL)
2101                 return -1;
2102
2103         if (!pipeline_is_running(p)) {
2104                 status = rte_table_action_ttl_read(table->a,
2105                                 rule->data,
2106                                 stats,
2107                                 clear);
2108
2109                 return status;
2110         }
2111
2112         /* Allocate request */
2113         req = pipeline_msg_alloc();
2114         if (req == NULL)
2115                 return -1;
2116
2117         /* Write request */
2118         req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
2119         req->id = table_id;
2120         req->table_rule_ttl_read.data = rule->data;
2121         req->table_rule_ttl_read.clear = clear;
2122
2123         /* Send request and wait for response */
2124         rsp = pipeline_msg_send_recv(p, req);
2125
2126         /* Read response */
2127         status = rsp->status;
2128         if (status == 0)
2129                 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2130
2131         /* Free response */
2132         pipeline_msg_free(rsp);
2133
2134         return status;
2135 }
2136
2137 int
2138 pipeline_table_rule_time_read(const char *pipeline_name,
2139         uint32_t table_id,
2140         struct table_rule_match *match,
2141         uint64_t *timestamp)
2142 {
2143         struct pipeline *p;
2144         struct table *table;
2145         struct pipeline_msg_req *req;
2146         struct pipeline_msg_rsp *rsp;
2147         struct table_rule *rule;
2148         int status;
2149
2150         /* Check input params */
2151         if ((pipeline_name == NULL) ||
2152                 (match == NULL) ||
2153                 (timestamp == NULL))
2154                 return -1;
2155
2156         p = pipeline_find(pipeline_name);
2157         if ((p == NULL) ||
2158                 (table_id >= p->n_tables) ||
2159                 match_check(match, p, table_id))
2160                 return -1;
2161
2162         table = &p->table[table_id];
2163
2164         rule = table_rule_find(table, match);
2165         if (rule == NULL)
2166                 return -1;
2167
2168         if (!pipeline_is_running(p)) {
2169                 status = rte_table_action_time_read(table->a,
2170                                 rule->data,
2171                                 timestamp);
2172
2173                 return status;
2174         }
2175
2176         /* Allocate request */
2177         req = pipeline_msg_alloc();
2178         if (req == NULL)
2179                 return -1;
2180
2181         /* Write request */
2182         req->type = PIPELINE_REQ_TABLE_RULE_TIME_READ;
2183         req->id = table_id;
2184         req->table_rule_time_read.data = rule->data;
2185
2186         /* Send request and wait for response */
2187         rsp = pipeline_msg_send_recv(p, req);
2188
2189         /* Read response */
2190         status = rsp->status;
2191         if (status == 0)
2192                 *timestamp = rsp->table_rule_time_read.timestamp;
2193
2194         /* Free response */
2195         pipeline_msg_free(rsp);
2196
2197         return status;
2198 }
2199
2200 /**
2201  * Data plane threads: message handling
2202  */
2203 static inline struct pipeline_msg_req *
2204 pipeline_msg_recv(struct rte_ring *msgq_req)
2205 {
2206         struct pipeline_msg_req *req;
2207
2208         int status = rte_ring_sc_dequeue(msgq_req, (void **) &req);
2209
2210         if (status != 0)
2211                 return NULL;
2212
2213         return req;
2214 }
2215
2216 static inline void
2217 pipeline_msg_send(struct rte_ring *msgq_rsp,
2218         struct pipeline_msg_rsp *rsp)
2219 {
2220         int status;
2221
2222         do {
2223                 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2224         } while (status == -ENOBUFS);
2225 }
2226
2227 static struct pipeline_msg_rsp *
2228 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2229         struct pipeline_msg_req *req)
2230 {
2231         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2232         uint32_t port_id = req->id;
2233         int clear = req->port_in_stats_read.clear;
2234
2235         rsp->status = rte_pipeline_port_in_stats_read(p->p,
2236                 port_id,
2237                 &rsp->port_in_stats_read.stats,
2238                 clear);
2239
2240         return rsp;
2241 }
2242
2243 static struct pipeline_msg_rsp *
2244 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2245         struct pipeline_msg_req *req)
2246 {
2247         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2248         uint32_t port_id = req->id;
2249
2250         rsp->status = rte_pipeline_port_in_enable(p->p,
2251                 port_id);
2252
2253         return rsp;
2254 }
2255
2256 static struct pipeline_msg_rsp *
2257 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2258         struct pipeline_msg_req *req)
2259 {
2260         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2261         uint32_t port_id = req->id;
2262
2263         rsp->status = rte_pipeline_port_in_disable(p->p,
2264                 port_id);
2265
2266         return rsp;
2267 }
2268
2269 static struct pipeline_msg_rsp *
2270 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2271         struct pipeline_msg_req *req)
2272 {
2273         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2274         uint32_t port_id = req->id;
2275         int clear = req->port_out_stats_read.clear;
2276
2277         rsp->status = rte_pipeline_port_out_stats_read(p->p,
2278                 port_id,
2279                 &rsp->port_out_stats_read.stats,
2280                 clear);
2281
2282         return rsp;
2283 }
2284
2285 static struct pipeline_msg_rsp *
2286 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2287         struct pipeline_msg_req *req)
2288 {
2289         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2290         uint32_t port_id = req->id;
2291         int clear = req->table_stats_read.clear;
2292
2293         rsp->status = rte_pipeline_table_stats_read(p->p,
2294                 port_id,
2295                 &rsp->table_stats_read.stats,
2296                 clear);
2297
2298         return rsp;
2299 }
2300
2301 static int
2302 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2303 {
2304         if (depth > 128)
2305                 return -1;
2306
2307         switch (depth / 32) {
2308         case 0:
2309                 depth32[0] = depth;
2310                 depth32[1] = 0;
2311                 depth32[2] = 0;
2312                 depth32[3] = 0;
2313                 return 0;
2314
2315         case 1:
2316                 depth32[0] = 32;
2317                 depth32[1] = depth - 32;
2318                 depth32[2] = 0;
2319                 depth32[3] = 0;
2320                 return 0;
2321
2322         case 2:
2323                 depth32[0] = 32;
2324                 depth32[1] = 32;
2325                 depth32[2] = depth - 64;
2326                 depth32[3] = 0;
2327                 return 0;
2328
2329         case 3:
2330                 depth32[0] = 32;
2331                 depth32[1] = 32;
2332                 depth32[2] = 32;
2333                 depth32[3] = depth - 96;
2334                 return 0;
2335
2336         case 4:
2337                 depth32[0] = 32;
2338                 depth32[1] = 32;
2339                 depth32[2] = 32;
2340                 depth32[3] = 32;
2341                 return 0;
2342
2343         default:
2344                 return -1;
2345         }
2346 }
2347
2348 static int
2349 match_convert(struct table_rule_match *mh,
2350         union table_rule_match_low_level *ml,
2351         int add)
2352 {
2353         memset(ml, 0, sizeof(*ml));
2354
2355         switch (mh->match_type) {
2356         case TABLE_ACL:
2357                 if (mh->match.acl.ip_version)
2358                         if (add) {
2359                                 ml->acl_add.field_value[0].value.u8 =
2360                                         mh->match.acl.proto;
2361                                 ml->acl_add.field_value[0].mask_range.u8 =
2362                                         mh->match.acl.proto_mask;
2363
2364                                 ml->acl_add.field_value[1].value.u32 =
2365                                         mh->match.acl.ipv4.sa;
2366                                 ml->acl_add.field_value[1].mask_range.u32 =
2367                                         mh->match.acl.sa_depth;
2368
2369                                 ml->acl_add.field_value[2].value.u32 =
2370                                         mh->match.acl.ipv4.da;
2371                                 ml->acl_add.field_value[2].mask_range.u32 =
2372                                         mh->match.acl.da_depth;
2373
2374                                 ml->acl_add.field_value[3].value.u16 =
2375                                         mh->match.acl.sp0;
2376                                 ml->acl_add.field_value[3].mask_range.u16 =
2377                                         mh->match.acl.sp1;
2378
2379                                 ml->acl_add.field_value[4].value.u16 =
2380                                         mh->match.acl.dp0;
2381                                 ml->acl_add.field_value[4].mask_range.u16 =
2382                                         mh->match.acl.dp1;
2383
2384                                 ml->acl_add.priority =
2385                                         (int32_t) mh->match.acl.priority;
2386                         } else {
2387                                 ml->acl_delete.field_value[0].value.u8 =
2388                                         mh->match.acl.proto;
2389                                 ml->acl_delete.field_value[0].mask_range.u8 =
2390                                         mh->match.acl.proto_mask;
2391
2392                                 ml->acl_delete.field_value[1].value.u32 =
2393                                         mh->match.acl.ipv4.sa;
2394                                 ml->acl_delete.field_value[1].mask_range.u32 =
2395                                         mh->match.acl.sa_depth;
2396
2397                                 ml->acl_delete.field_value[2].value.u32 =
2398                                         mh->match.acl.ipv4.da;
2399                                 ml->acl_delete.field_value[2].mask_range.u32 =
2400                                         mh->match.acl.da_depth;
2401
2402                                 ml->acl_delete.field_value[3].value.u16 =
2403                                         mh->match.acl.sp0;
2404                                 ml->acl_delete.field_value[3].mask_range.u16 =
2405                                         mh->match.acl.sp1;
2406
2407                                 ml->acl_delete.field_value[4].value.u16 =
2408                                         mh->match.acl.dp0;
2409                                 ml->acl_delete.field_value[4].mask_range.u16 =
2410                                         mh->match.acl.dp1;
2411                         }
2412                 else
2413                         if (add) {
2414                                 uint32_t *sa32 =
2415                                         (uint32_t *) mh->match.acl.ipv6.sa;
2416                                 uint32_t *da32 =
2417                                         (uint32_t *) mh->match.acl.ipv6.da;
2418                                 uint32_t sa32_depth[4], da32_depth[4];
2419                                 int status;
2420
2421                                 status = match_convert_ipv6_depth(
2422                                         mh->match.acl.sa_depth,
2423                                         sa32_depth);
2424                                 if (status)
2425                                         return status;
2426
2427                                 status = match_convert_ipv6_depth(
2428                                         mh->match.acl.da_depth,
2429                                         da32_depth);
2430                                 if (status)
2431                                         return status;
2432
2433                                 ml->acl_add.field_value[0].value.u8 =
2434                                         mh->match.acl.proto;
2435                                 ml->acl_add.field_value[0].mask_range.u8 =
2436                                         mh->match.acl.proto_mask;
2437
2438                                 ml->acl_add.field_value[1].value.u32 =
2439                                         rte_be_to_cpu_32(sa32[0]);
2440                                 ml->acl_add.field_value[1].mask_range.u32 =
2441                                         sa32_depth[0];
2442                                 ml->acl_add.field_value[2].value.u32 =
2443                                         rte_be_to_cpu_32(sa32[1]);
2444                                 ml->acl_add.field_value[2].mask_range.u32 =
2445                                         sa32_depth[1];
2446                                 ml->acl_add.field_value[3].value.u32 =
2447                                         rte_be_to_cpu_32(sa32[2]);
2448                                 ml->acl_add.field_value[3].mask_range.u32 =
2449                                         sa32_depth[2];
2450                                 ml->acl_add.field_value[4].value.u32 =
2451                                         rte_be_to_cpu_32(sa32[3]);
2452                                 ml->acl_add.field_value[4].mask_range.u32 =
2453                                         sa32_depth[3];
2454
2455                                 ml->acl_add.field_value[5].value.u32 =
2456                                         rte_be_to_cpu_32(da32[0]);
2457                                 ml->acl_add.field_value[5].mask_range.u32 =
2458                                         da32_depth[0];
2459                                 ml->acl_add.field_value[6].value.u32 =
2460                                         rte_be_to_cpu_32(da32[1]);
2461                                 ml->acl_add.field_value[6].mask_range.u32 =
2462                                         da32_depth[1];
2463                                 ml->acl_add.field_value[7].value.u32 =
2464                                         rte_be_to_cpu_32(da32[2]);
2465                                 ml->acl_add.field_value[7].mask_range.u32 =
2466                                         da32_depth[2];
2467                                 ml->acl_add.field_value[8].value.u32 =
2468                                         rte_be_to_cpu_32(da32[3]);
2469                                 ml->acl_add.field_value[8].mask_range.u32 =
2470                                         da32_depth[3];
2471
2472                                 ml->acl_add.field_value[9].value.u16 =
2473                                         mh->match.acl.sp0;
2474                                 ml->acl_add.field_value[9].mask_range.u16 =
2475                                         mh->match.acl.sp1;
2476
2477                                 ml->acl_add.field_value[10].value.u16 =
2478                                         mh->match.acl.dp0;
2479                                 ml->acl_add.field_value[10].mask_range.u16 =
2480                                         mh->match.acl.dp1;
2481
2482                                 ml->acl_add.priority =
2483                                         (int32_t) mh->match.acl.priority;
2484                         } else {
2485                                 uint32_t *sa32 =
2486                                         (uint32_t *) mh->match.acl.ipv6.sa;
2487                                 uint32_t *da32 =
2488                                         (uint32_t *) mh->match.acl.ipv6.da;
2489                                 uint32_t sa32_depth[4], da32_depth[4];
2490                                 int status;
2491
2492                                 status = match_convert_ipv6_depth(
2493                                         mh->match.acl.sa_depth,
2494                                         sa32_depth);
2495                                 if (status)
2496                                         return status;
2497
2498                                 status = match_convert_ipv6_depth(
2499                                         mh->match.acl.da_depth,
2500                                         da32_depth);
2501                                 if (status)
2502                                         return status;
2503
2504                                 ml->acl_delete.field_value[0].value.u8 =
2505                                         mh->match.acl.proto;
2506                                 ml->acl_delete.field_value[0].mask_range.u8 =
2507                                         mh->match.acl.proto_mask;
2508
2509                                 ml->acl_delete.field_value[1].value.u32 =
2510                                         rte_be_to_cpu_32(sa32[0]);
2511                                 ml->acl_delete.field_value[1].mask_range.u32 =
2512                                         sa32_depth[0];
2513                                 ml->acl_delete.field_value[2].value.u32 =
2514                                         rte_be_to_cpu_32(sa32[1]);
2515                                 ml->acl_delete.field_value[2].mask_range.u32 =
2516                                         sa32_depth[1];
2517                                 ml->acl_delete.field_value[3].value.u32 =
2518                                         rte_be_to_cpu_32(sa32[2]);
2519                                 ml->acl_delete.field_value[3].mask_range.u32 =
2520                                         sa32_depth[2];
2521                                 ml->acl_delete.field_value[4].value.u32 =
2522                                         rte_be_to_cpu_32(sa32[3]);
2523                                 ml->acl_delete.field_value[4].mask_range.u32 =
2524                                         sa32_depth[3];
2525
2526                                 ml->acl_delete.field_value[5].value.u32 =
2527                                         rte_be_to_cpu_32(da32[0]);
2528                                 ml->acl_delete.field_value[5].mask_range.u32 =
2529                                         da32_depth[0];
2530                                 ml->acl_delete.field_value[6].value.u32 =
2531                                         rte_be_to_cpu_32(da32[1]);
2532                                 ml->acl_delete.field_value[6].mask_range.u32 =
2533                                         da32_depth[1];
2534                                 ml->acl_delete.field_value[7].value.u32 =
2535                                         rte_be_to_cpu_32(da32[2]);
2536                                 ml->acl_delete.field_value[7].mask_range.u32 =
2537                                         da32_depth[2];
2538                                 ml->acl_delete.field_value[8].value.u32 =
2539                                         rte_be_to_cpu_32(da32[3]);
2540                                 ml->acl_delete.field_value[8].mask_range.u32 =
2541                                         da32_depth[3];
2542
2543                                 ml->acl_delete.field_value[9].value.u16 =
2544                                         mh->match.acl.sp0;
2545                                 ml->acl_delete.field_value[9].mask_range.u16 =
2546                                         mh->match.acl.sp1;
2547
2548                                 ml->acl_delete.field_value[10].value.u16 =
2549                                         mh->match.acl.dp0;
2550                                 ml->acl_delete.field_value[10].mask_range.u16 =
2551                                         mh->match.acl.dp1;
2552                         }
2553                 return 0;
2554
2555         case TABLE_ARRAY:
2556                 ml->array.pos = mh->match.array.pos;
2557                 return 0;
2558
2559         case TABLE_HASH:
2560                 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2561                 return 0;
2562
2563         case TABLE_LPM:
2564                 if (mh->match.lpm.ip_version) {
2565                         ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2566                         ml->lpm_ipv4.depth = mh->match.lpm.depth;
2567                 } else {
2568                         memcpy(ml->lpm_ipv6.ip,
2569                                 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2570                         ml->lpm_ipv6.depth = mh->match.lpm.depth;
2571                 }
2572
2573                 return 0;
2574
2575         default:
2576                 return -1;
2577         }
2578 }
2579
2580 static int
2581 action_convert(struct rte_table_action *a,
2582         struct table_rule_action *action,
2583         struct rte_pipeline_table_entry *data)
2584 {
2585         int status;
2586
2587         /* Apply actions */
2588         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2589                 status = rte_table_action_apply(a,
2590                         data,
2591                         RTE_TABLE_ACTION_FWD,
2592                         &action->fwd);
2593
2594                 if (status)
2595                         return status;
2596         }
2597
2598         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2599                 status = rte_table_action_apply(a,
2600                         data,
2601                         RTE_TABLE_ACTION_LB,
2602                         &action->lb);
2603
2604                 if (status)
2605                         return status;
2606         }
2607
2608         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2609                 status = rte_table_action_apply(a,
2610                         data,
2611                         RTE_TABLE_ACTION_MTR,
2612                         &action->mtr);
2613
2614                 if (status)
2615                         return status;
2616         }
2617
2618         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2619                 status = rte_table_action_apply(a,
2620                         data,
2621                         RTE_TABLE_ACTION_TM,
2622                         &action->tm);
2623
2624                 if (status)
2625                         return status;
2626         }
2627
2628         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2629                 status = rte_table_action_apply(a,
2630                         data,
2631                         RTE_TABLE_ACTION_ENCAP,
2632                         &action->encap);
2633
2634                 if (status)
2635                         return status;
2636         }
2637
2638         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2639                 status = rte_table_action_apply(a,
2640                         data,
2641                         RTE_TABLE_ACTION_NAT,
2642                         &action->nat);
2643
2644                 if (status)
2645                         return status;
2646         }
2647
2648         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2649                 status = rte_table_action_apply(a,
2650                         data,
2651                         RTE_TABLE_ACTION_TTL,
2652                         &action->ttl);
2653
2654                 if (status)
2655                         return status;
2656         }
2657
2658         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2659                 status = rte_table_action_apply(a,
2660                         data,
2661                         RTE_TABLE_ACTION_STATS,
2662                         &action->stats);
2663
2664                 if (status)
2665                         return status;
2666         }
2667
2668         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2669                 status = rte_table_action_apply(a,
2670                         data,
2671                         RTE_TABLE_ACTION_TIME,
2672                         &action->time);
2673
2674                 if (status)
2675                         return status;
2676         }
2677
2678         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2679                 status = rte_table_action_apply(a,
2680                         data,
2681                         RTE_TABLE_ACTION_SYM_CRYPTO,
2682                         &action->sym_crypto);
2683
2684                 if (status)
2685                         return status;
2686         }
2687
2688         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2689                 status = rte_table_action_apply(a,
2690                         data,
2691                         RTE_TABLE_ACTION_TAG,
2692                         &action->tag);
2693
2694                 if (status)
2695                         return status;
2696         }
2697
2698         if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2699                 status = rte_table_action_apply(a,
2700                         data,
2701                         RTE_TABLE_ACTION_DECAP,
2702                         &action->decap);
2703
2704                 if (status)
2705                         return status;
2706         }
2707
2708         return 0;
2709 }
2710
2711 static struct pipeline_msg_rsp *
2712 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2713         struct pipeline_msg_req *req)
2714 {
2715         union table_rule_match_low_level match_ll;
2716         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2717         struct table_rule_match *match = &req->table_rule_add.match;
2718         struct table_rule_action *action = &req->table_rule_add.action;
2719         struct rte_pipeline_table_entry *data_in, *data_out;
2720         uint32_t table_id = req->id;
2721         int key_found, status;
2722         struct rte_table_action *a = p->table_data[table_id].a;
2723
2724         /* Apply actions */
2725         memset(p->buffer, 0, sizeof(p->buffer));
2726         data_in = (struct rte_pipeline_table_entry *) p->buffer;
2727
2728         status = match_convert(match, &match_ll, 1);
2729         if (status) {
2730                 rsp->status = -1;
2731                 return rsp;
2732         }
2733
2734         status = action_convert(a, action, data_in);
2735         if (status) {
2736                 rsp->status = -1;
2737                 return rsp;
2738         }
2739
2740         status = rte_pipeline_table_entry_add(p->p,
2741                 table_id,
2742                 &match_ll,
2743                 data_in,
2744                 &key_found,
2745                 &data_out);
2746         if (status) {
2747                 rsp->status = -1;
2748                 return rsp;
2749         }
2750
2751         /* Write response */
2752         rsp->status = 0;
2753         rsp->table_rule_add.data = data_out;
2754
2755         return rsp;
2756 }
2757
2758 static struct pipeline_msg_rsp *
2759 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2760         struct pipeline_msg_req *req)
2761 {
2762         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2763         struct table_rule_action *action = &req->table_rule_add_default.action;
2764         struct rte_pipeline_table_entry *data_in, *data_out;
2765         uint32_t table_id = req->id;
2766         int status;
2767
2768         /* Apply actions */
2769         memset(p->buffer, 0, sizeof(p->buffer));
2770         data_in = (struct rte_pipeline_table_entry *) p->buffer;
2771
2772         data_in->action = action->fwd.action;
2773         if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2774                 data_in->port_id = action->fwd.id;
2775         if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2776                 data_in->table_id = action->fwd.id;
2777
2778         /* Add default rule to table */
2779         status = rte_pipeline_table_default_entry_add(p->p,
2780                 table_id,
2781                 data_in,
2782                 &data_out);
2783         if (status) {
2784                 rsp->status = -1;
2785                 return rsp;
2786         }
2787
2788         /* Write response */
2789         rsp->status = 0;
2790         rsp->table_rule_add_default.data = data_out;
2791
2792         return rsp;
2793 }
2794
2795 static struct pipeline_msg_rsp *
2796 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2797         struct pipeline_msg_req *req)
2798 {
2799         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2800
2801         uint32_t table_id = req->id;
2802         struct table_rule_list *list = req->table_rule_add_bulk.list;
2803         uint32_t bulk = req->table_rule_add_bulk.bulk;
2804
2805         uint32_t n_rules_added;
2806         int status;
2807
2808         struct table_ll table_ll = {
2809                 .p = p->p,
2810                 .table_id = table_id,
2811                 .a = p->table_data[table_id].a,
2812                 .bulk_supported = bulk,
2813         };
2814
2815         status = table_rule_add_bulk_ll(&table_ll, list, &n_rules_added);
2816         if (status) {
2817                 rsp->status = -1;
2818                 rsp->table_rule_add_bulk.n_rules = 0;
2819                 return rsp;
2820         }
2821
2822         /* Write response */
2823         rsp->status = 0;
2824         rsp->table_rule_add_bulk.n_rules = n_rules_added;
2825         return rsp;
2826 }
2827
2828 static struct pipeline_msg_rsp *
2829 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2830         struct pipeline_msg_req *req)
2831 {
2832         union table_rule_match_low_level match_ll;
2833         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2834         struct table_rule_match *match = &req->table_rule_delete.match;
2835         uint32_t table_id = req->id;
2836         int key_found, status;
2837
2838         status = match_convert(match, &match_ll, 0);
2839         if (status) {
2840                 rsp->status = -1;
2841                 return rsp;
2842         }
2843
2844         rsp->status = rte_pipeline_table_entry_delete(p->p,
2845                 table_id,
2846                 &match_ll,
2847                 &key_found,
2848                 NULL);
2849
2850         return rsp;
2851 }
2852
2853 static struct pipeline_msg_rsp *
2854 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2855         struct pipeline_msg_req *req)
2856 {
2857         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2858         uint32_t table_id = req->id;
2859
2860         rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2861                 table_id,
2862                 NULL);
2863
2864         return rsp;
2865 }
2866
2867 static struct pipeline_msg_rsp *
2868 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2869         struct pipeline_msg_req *req)
2870 {
2871         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2872         uint32_t table_id = req->id;
2873         void *data = req->table_rule_stats_read.data;
2874         int clear = req->table_rule_stats_read.clear;
2875         struct rte_table_action *a = p->table_data[table_id].a;
2876
2877         rsp->status = rte_table_action_stats_read(a,
2878                 data,
2879                 &rsp->table_rule_stats_read.stats,
2880                 clear);
2881
2882         return rsp;
2883 }
2884
2885 static struct pipeline_msg_rsp *
2886 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2887         struct pipeline_msg_req *req)
2888 {
2889         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2890         uint32_t table_id = req->id;
2891         uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2892         struct rte_table_action_meter_profile *profile =
2893                 &req->table_mtr_profile_add.profile;
2894         struct rte_table_action *a = p->table_data[table_id].a;
2895
2896         rsp->status = rte_table_action_meter_profile_add(a,
2897                 meter_profile_id,
2898                 profile);
2899
2900         return rsp;
2901 }
2902
2903 static struct pipeline_msg_rsp *
2904 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2905         struct pipeline_msg_req *req)
2906 {
2907         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2908         uint32_t table_id = req->id;
2909         uint32_t meter_profile_id =
2910                 req->table_mtr_profile_delete.meter_profile_id;
2911         struct rte_table_action *a = p->table_data[table_id].a;
2912
2913         rsp->status = rte_table_action_meter_profile_delete(a,
2914                 meter_profile_id);
2915
2916         return rsp;
2917 }
2918
2919 static struct pipeline_msg_rsp *
2920 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2921         struct pipeline_msg_req *req)
2922 {
2923         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2924         uint32_t table_id = req->id;
2925         void *data = req->table_rule_mtr_read.data;
2926         uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2927         int clear = req->table_rule_mtr_read.clear;
2928         struct rte_table_action *a = p->table_data[table_id].a;
2929
2930         rsp->status = rte_table_action_meter_read(a,
2931                 data,
2932                 tc_mask,
2933                 &rsp->table_rule_mtr_read.stats,
2934                 clear);
2935
2936         return rsp;
2937 }
2938
2939 static struct pipeline_msg_rsp *
2940 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2941         struct pipeline_msg_req *req)
2942 {
2943         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2944         uint32_t table_id = req->id;
2945         uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2946         struct rte_table_action_dscp_table *dscp_table =
2947                 &req->table_dscp_table_update.dscp_table;
2948         struct rte_table_action *a = p->table_data[table_id].a;
2949
2950         rsp->status = rte_table_action_dscp_table_update(a,
2951                 dscp_mask,
2952                 dscp_table);
2953
2954         return rsp;
2955 }
2956
2957 static struct pipeline_msg_rsp *
2958 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2959         struct pipeline_msg_req *req)
2960 {
2961         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2962         uint32_t table_id = req->id;
2963         void *data = req->table_rule_ttl_read.data;
2964         int clear = req->table_rule_ttl_read.clear;
2965         struct rte_table_action *a = p->table_data[table_id].a;
2966
2967         rsp->status = rte_table_action_ttl_read(a,
2968                 data,
2969                 &rsp->table_rule_ttl_read.stats,
2970                 clear);
2971
2972         return rsp;
2973 }
2974
2975 static struct pipeline_msg_rsp *
2976 pipeline_msg_handle_table_rule_time_read(struct pipeline_data *p,
2977         struct pipeline_msg_req *req)
2978 {
2979         struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
2980         uint32_t table_id = req->id;
2981         void *data = req->table_rule_time_read.data;
2982         struct rte_table_action *a = p->table_data[table_id].a;
2983
2984         rsp->status = rte_table_action_time_read(a,
2985                 data,
2986                 &rsp->table_rule_time_read.timestamp);
2987
2988         return rsp;
2989 }
2990
2991 static void
2992 pipeline_msg_handle(struct pipeline_data *p)
2993 {
2994         for ( ; ; ) {
2995                 struct pipeline_msg_req *req;
2996                 struct pipeline_msg_rsp *rsp;
2997
2998                 req = pipeline_msg_recv(p->msgq_req);
2999                 if (req == NULL)
3000                         break;
3001
3002                 switch (req->type) {
3003                 case PIPELINE_REQ_PORT_IN_STATS_READ:
3004                         rsp = pipeline_msg_handle_port_in_stats_read(p, req);
3005                         break;
3006
3007                 case PIPELINE_REQ_PORT_IN_ENABLE:
3008                         rsp = pipeline_msg_handle_port_in_enable(p, req);
3009                         break;
3010
3011                 case PIPELINE_REQ_PORT_IN_DISABLE:
3012                         rsp = pipeline_msg_handle_port_in_disable(p, req);
3013                         break;
3014
3015                 case PIPELINE_REQ_PORT_OUT_STATS_READ:
3016                         rsp = pipeline_msg_handle_port_out_stats_read(p, req);
3017                         break;
3018
3019                 case PIPELINE_REQ_TABLE_STATS_READ:
3020                         rsp = pipeline_msg_handle_table_stats_read(p, req);
3021                         break;
3022
3023                 case PIPELINE_REQ_TABLE_RULE_ADD:
3024                         rsp = pipeline_msg_handle_table_rule_add(p, req);
3025                         break;
3026
3027                 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
3028                         rsp = pipeline_msg_handle_table_rule_add_default(p,     req);
3029                         break;
3030
3031                 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
3032                         rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
3033                         break;
3034
3035                 case PIPELINE_REQ_TABLE_RULE_DELETE:
3036                         rsp = pipeline_msg_handle_table_rule_delete(p, req);
3037                         break;
3038
3039                 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
3040                         rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
3041                         break;
3042
3043                 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
3044                         rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
3045                         break;
3046
3047                 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
3048                         rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
3049                         break;
3050
3051                 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
3052                         rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
3053                         break;
3054
3055                 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
3056                         rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
3057                         break;
3058
3059                 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
3060                         rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
3061                         break;
3062
3063                 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
3064                         rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
3065                         break;
3066
3067                 case PIPELINE_REQ_TABLE_RULE_TIME_READ:
3068                         rsp = pipeline_msg_handle_table_rule_time_read(p, req);
3069                         break;
3070
3071                 default:
3072                         rsp = (struct pipeline_msg_rsp *) req;
3073                         rsp->status = -1;
3074                 }
3075
3076                 pipeline_msg_send(p->msgq_rsp, rsp);
3077         }
3078 }
3079
3080 /**
3081  * Data plane threads: main
3082  */
3083 int
3084 thread_main(void *arg __rte_unused)
3085 {
3086         struct thread_data *t;
3087         uint32_t thread_id, i;
3088
3089         thread_id = rte_lcore_id();
3090         t = &thread_data[thread_id];
3091
3092         /* Dispatch loop */
3093         for (i = 0; ; i++) {
3094                 uint32_t j;
3095
3096                 /* Data Plane */
3097                 for (j = 0; j < t->n_pipelines; j++)
3098                         rte_pipeline_run(t->p[j]);
3099
3100                 /* Control Plane */
3101                 if ((i & 0xF) == 0) {
3102                         uint64_t time = rte_get_tsc_cycles();
3103                         uint64_t time_next_min = UINT64_MAX;
3104
3105                         if (time < t->time_next_min)
3106                                 continue;
3107
3108                         /* Pipeline message queues */
3109                         for (j = 0; j < t->n_pipelines; j++) {
3110                                 struct pipeline_data *p =
3111                                         &t->pipeline_data[j];
3112                                 uint64_t time_next = p->time_next;
3113
3114                                 if (time_next <= time) {
3115                                         pipeline_msg_handle(p);
3116                                         rte_pipeline_flush(p->p);
3117                                         time_next = time + p->timer_period;
3118                                         p->time_next = time_next;
3119                                 }
3120
3121                                 if (time_next < time_next_min)
3122                                         time_next_min = time_next;
3123                         }
3124
3125                         /* Thread message queues */
3126                         {
3127                                 uint64_t time_next = t->time_next;
3128
3129                                 if (time_next <= time) {
3130                                         thread_msg_handle(t);
3131                                         time_next = time + t->timer_period;
3132                                         t->time_next = time_next;
3133                                 }
3134
3135                                 if (time_next < time_next_min)
3136                                         time_next_min = time_next;
3137                         }
3138
3139                         t->time_next_min = time_next_min;
3140                 }
3141         }
3142
3143         return 0;
3144 }