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