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