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