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