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