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