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