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