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