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