1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
7 #include <rte_common.h>
8 #include <rte_cycles.h>
10 #include <rte_service_component.h>
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"
21 * Master thread: data plane thread init
24 softnic_thread_free(struct pmd_internals *softnic)
28 RTE_LCORE_FOREACH_SLAVE(i) {
29 struct softnic_thread *t = &softnic->thread[i];
33 rte_ring_free(t->msgq_req);
36 rte_ring_free(t->msgq_rsp);
41 softnic_thread_init(struct pmd_internals *softnic)
45 for (i = 0; i < RTE_MAX_LCORE; i++) {
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);
53 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ",
57 msgq_req = rte_ring_create(ring_name,
60 RING_F_SP_ENQ | RING_F_SC_DEQ);
62 if (msgq_req == NULL) {
63 softnic_thread_free(softnic);
67 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP",
71 msgq_rsp = rte_ring_create(ring_name,
74 RING_F_SP_ENQ | RING_F_SC_DEQ);
76 if (msgq_rsp == NULL) {
77 softnic_thread_free(softnic);
81 /* Master thread records */
82 t->msgq_req = msgq_req;
83 t->msgq_rsp = msgq_rsp;
84 t->service_id = UINT32_MAX;
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;
100 thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id)
102 if (thread_id == rte_get_master_lcore())
103 return 0; /* FALSE */
105 if (softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_SERVICE))
107 if (!softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_RTE))
110 return 0; /* FALSE */
114 thread_is_running(uint32_t thread_id)
116 enum rte_lcore_state_t thread_state;
118 thread_state = rte_eal_get_lcore_state(thread_id);
119 return (thread_state == RUNNING)? 1 : 0;
123 rte_pmd_softnic_run_internal(void *arg);
126 thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
128 struct rte_service_spec service_params;
129 struct softnic_thread *t = &softnic->thread[thread_id];
130 struct rte_eth_dev *dev;
135 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
139 dev = &rte_eth_devices[port_id];
140 snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
141 softnic->params.name,
143 service_params.callback = rte_pmd_softnic_run_internal;
144 service_params.callback_userdata = dev;
145 service_params.capabilities = 0;
146 service_params.socket_id = (int)softnic->params.cpu_id;
148 /* service register */
149 status = rte_service_component_register(&service_params, &t->service_id);
153 status = rte_service_component_runstate_set(t->service_id, 1);
155 rte_service_component_unregister(t->service_id);
156 t->service_id = UINT32_MAX;
160 status = rte_service_runstate_set(t->service_id, 1);
162 rte_service_component_runstate_set(t->service_id, 0);
163 rte_service_component_unregister(t->service_id);
164 t->service_id = UINT32_MAX;
168 /* service map to thread */
169 status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
171 rte_service_runstate_set(t->service_id, 0);
172 rte_service_component_runstate_set(t->service_id, 0);
173 rte_service_component_unregister(t->service_id);
174 t->service_id = UINT32_MAX;
182 thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
184 struct softnic_thread *t = &softnic->thread[thread_id];
186 /* service unmap from thread */
187 rte_service_map_lcore_set(t->service_id, thread_id, 0);
189 /* service unregister */
190 rte_service_runstate_set(t->service_id, 0);
191 rte_service_component_runstate_set(t->service_id, 0);
192 rte_service_component_unregister(t->service_id);
194 t->service_id = UINT32_MAX;
198 * Pipeline is running when:
199 * (A) Pipeline is mapped to a data plane thread AND
200 * (B) Its data plane thread is in RUNNING state.
203 pipeline_is_running(struct pipeline *p)
208 return thread_is_running(p->thread_id);
212 * Master thread & data plane threads: message passing
214 enum thread_req_type {
215 THREAD_REQ_PIPELINE_ENABLE = 0,
216 THREAD_REQ_PIPELINE_DISABLE,
220 struct thread_msg_req {
221 enum thread_req_type type;
225 struct rte_pipeline *p;
227 struct rte_table_action *a;
228 } table[RTE_PIPELINE_TABLE_MAX];
229 struct rte_ring *msgq_req;
230 struct rte_ring *msgq_rsp;
231 uint32_t timer_period_ms;
236 struct rte_pipeline *p;
241 struct thread_msg_rsp {
248 static struct thread_msg_req *
249 thread_msg_alloc(void)
251 size_t size = RTE_MAX(sizeof(struct thread_msg_req),
252 sizeof(struct thread_msg_rsp));
254 return calloc(1, size);
258 thread_msg_free(struct thread_msg_rsp *rsp)
263 static struct thread_msg_rsp *
264 thread_msg_send_recv(struct pmd_internals *softnic,
266 struct thread_msg_req *req)
268 struct softnic_thread *t = &softnic->thread[thread_id];
269 struct rte_ring *msgq_req = t->msgq_req;
270 struct rte_ring *msgq_rsp = t->msgq_rsp;
271 struct thread_msg_rsp *rsp;
276 status = rte_ring_sp_enqueue(msgq_req, req);
277 } while (status == -ENOBUFS);
281 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
282 } while (status != 0);
288 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
290 const char *pipeline_name)
292 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
293 struct thread_msg_req *req;
294 struct thread_msg_rsp *rsp;
295 uint32_t n_pipelines, i;
298 /* Check input params */
299 if (!thread_is_valid(softnic, thread_id) ||
301 (p->n_ports_in == 0) ||
302 (p->n_ports_out == 0) ||
303 (p->n_tables == 0) ||
307 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
308 if (n_pipelines >= THREAD_PIPELINES_MAX)
311 if (softnic->params.sc && (n_pipelines == 0)) {
312 status = thread_sc_service_up(softnic, thread_id);
317 if (!thread_is_running(thread_id)) {
318 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
319 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
321 /* Data plane thread */
322 td->p[td->n_pipelines] = p->p;
325 for (i = 0; i < p->n_tables; i++)
326 tdp->table_data[i].a =
328 tdp->n_tables = p->n_tables;
330 tdp->msgq_req = p->msgq_req;
331 tdp->msgq_rsp = p->msgq_rsp;
332 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
333 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
338 p->thread_id = thread_id;
344 /* Allocate request */
345 req = thread_msg_alloc();
350 req->type = THREAD_REQ_PIPELINE_ENABLE;
351 req->pipeline_enable.p = p->p;
352 for (i = 0; i < p->n_tables; i++)
353 req->pipeline_enable.table[i].a =
355 req->pipeline_enable.msgq_req = p->msgq_req;
356 req->pipeline_enable.msgq_rsp = p->msgq_rsp;
357 req->pipeline_enable.timer_period_ms = p->timer_period_ms;
358 req->pipeline_enable.n_tables = p->n_tables;
360 /* Send request and wait for response */
361 rsp = thread_msg_send_recv(softnic, thread_id, req);
364 status = rsp->status;
367 thread_msg_free(rsp);
369 /* Request completion */
373 p->thread_id = thread_id;
380 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
382 const char *pipeline_name)
384 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
385 struct thread_msg_req *req;
386 struct thread_msg_rsp *rsp;
387 uint32_t n_pipelines;
390 /* Check input params */
391 if (!thread_is_valid(softnic, thread_id) ||
393 (p->enabled && (p->thread_id != thread_id)))
399 if (!thread_is_running(thread_id)) {
400 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
403 for (i = 0; i < td->n_pipelines; i++) {
404 struct pipeline_data *tdp = &td->pipeline_data[i];
409 /* Data plane thread */
410 if (i < td->n_pipelines - 1) {
411 struct rte_pipeline *pipeline_last =
412 td->p[td->n_pipelines - 1];
413 struct pipeline_data *tdp_last =
414 &td->pipeline_data[td->n_pipelines - 1];
416 td->p[i] = pipeline_last;
417 memcpy(tdp, tdp_last, sizeof(*tdp));
428 if (softnic->params.sc && (td->n_pipelines == 0))
429 thread_sc_service_down(softnic, thread_id);
434 /* Allocate request */
435 req = thread_msg_alloc();
440 req->type = THREAD_REQ_PIPELINE_DISABLE;
441 req->pipeline_disable.p = p->p;
443 /* Send request and wait for response */
444 rsp = thread_msg_send_recv(softnic, thread_id, req);
447 status = rsp->status;
450 thread_msg_free(rsp);
452 /* Request completion */
458 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
459 if (softnic->params.sc && (n_pipelines == 0))
460 thread_sc_service_down(softnic, thread_id);
466 * Data plane threads: message handling
468 static inline struct thread_msg_req *
469 thread_msg_recv(struct rte_ring *msgq_req)
471 struct thread_msg_req *req;
473 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
482 thread_msg_send(struct rte_ring *msgq_rsp,
483 struct thread_msg_rsp *rsp)
488 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
489 } while (status == -ENOBUFS);
492 static struct thread_msg_rsp *
493 thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
494 struct thread_msg_req *req)
496 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
497 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
501 t->p[t->n_pipelines] = req->pipeline_enable.p;
503 p->p = req->pipeline_enable.p;
504 for (i = 0; i < req->pipeline_enable.n_tables; i++)
506 req->pipeline_enable.table[i].a;
508 p->n_tables = req->pipeline_enable.n_tables;
510 p->msgq_req = req->pipeline_enable.msgq_req;
511 p->msgq_rsp = req->pipeline_enable.msgq_rsp;
513 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
514 p->time_next = rte_get_tsc_cycles() + p->timer_period;
523 static struct thread_msg_rsp *
524 thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
525 struct thread_msg_req *req)
527 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
528 uint32_t n_pipelines = t->n_pipelines;
529 struct rte_pipeline *pipeline = req->pipeline_disable.p;
533 for (i = 0; i < n_pipelines; i++) {
534 struct pipeline_data *p = &t->pipeline_data[i];
536 if (p->p != pipeline)
539 if (i < n_pipelines - 1) {
540 struct rte_pipeline *pipeline_last =
541 t->p[n_pipelines - 1];
542 struct pipeline_data *p_last =
543 &t->pipeline_data[n_pipelines - 1];
545 t->p[i] = pipeline_last;
546 memcpy(p, p_last, sizeof(*p));
555 /* should not get here */
561 thread_msg_handle(struct softnic_thread_data *t)
564 struct thread_msg_req *req;
565 struct thread_msg_rsp *rsp;
567 req = thread_msg_recv(t->msgq_req);
572 case THREAD_REQ_PIPELINE_ENABLE:
573 rsp = thread_msg_handle_pipeline_enable(t, req);
576 case THREAD_REQ_PIPELINE_DISABLE:
577 rsp = thread_msg_handle_pipeline_disable(t, req);
581 rsp = (struct thread_msg_rsp *)req;
585 thread_msg_send(t->msgq_rsp, rsp);
590 * Master thread & data plane threads: message passing
592 enum pipeline_req_type {
594 PIPELINE_REQ_PORT_IN_STATS_READ,
595 PIPELINE_REQ_PORT_IN_ENABLE,
596 PIPELINE_REQ_PORT_IN_DISABLE,
599 PIPELINE_REQ_PORT_OUT_STATS_READ,
602 PIPELINE_REQ_TABLE_STATS_READ,
603 PIPELINE_REQ_TABLE_RULE_ADD,
604 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
605 PIPELINE_REQ_TABLE_RULE_ADD_BULK,
606 PIPELINE_REQ_TABLE_RULE_DELETE,
607 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
608 PIPELINE_REQ_TABLE_RULE_STATS_READ,
609 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
610 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
611 PIPELINE_REQ_TABLE_RULE_MTR_READ,
612 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
613 PIPELINE_REQ_TABLE_RULE_TTL_READ,
617 struct pipeline_msg_req_port_in_stats_read {
621 struct pipeline_msg_req_port_out_stats_read {
625 struct pipeline_msg_req_table_stats_read {
629 struct pipeline_msg_req_table_rule_add {
630 struct softnic_table_rule_match match;
631 struct softnic_table_rule_action action;
634 struct pipeline_msg_req_table_rule_add_default {
635 struct softnic_table_rule_action action;
638 struct pipeline_msg_req_table_rule_add_bulk {
639 struct softnic_table_rule_match *match;
640 struct softnic_table_rule_action *action;
646 struct pipeline_msg_req_table_rule_delete {
647 struct softnic_table_rule_match match;
650 struct pipeline_msg_req_table_rule_stats_read {
655 struct pipeline_msg_req_table_mtr_profile_add {
656 uint32_t meter_profile_id;
657 struct rte_table_action_meter_profile profile;
660 struct pipeline_msg_req_table_mtr_profile_delete {
661 uint32_t meter_profile_id;
664 struct pipeline_msg_req_table_rule_mtr_read {
670 struct pipeline_msg_req_table_dscp_table_update {
672 struct rte_table_action_dscp_table dscp_table;
675 struct pipeline_msg_req_table_rule_ttl_read {
680 struct pipeline_msg_req {
681 enum pipeline_req_type type;
682 uint32_t id; /* Port IN, port OUT or table ID */
686 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
687 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
688 struct pipeline_msg_req_table_stats_read table_stats_read;
689 struct pipeline_msg_req_table_rule_add table_rule_add;
690 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
691 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
692 struct pipeline_msg_req_table_rule_delete table_rule_delete;
693 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
694 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
695 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
696 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
697 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
698 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
702 struct pipeline_msg_rsp_port_in_stats_read {
703 struct rte_pipeline_port_in_stats stats;
706 struct pipeline_msg_rsp_port_out_stats_read {
707 struct rte_pipeline_port_out_stats stats;
710 struct pipeline_msg_rsp_table_stats_read {
711 struct rte_pipeline_table_stats stats;
714 struct pipeline_msg_rsp_table_rule_add {
718 struct pipeline_msg_rsp_table_rule_add_default {
722 struct pipeline_msg_rsp_table_rule_add_bulk {
726 struct pipeline_msg_rsp_table_rule_stats_read {
727 struct rte_table_action_stats_counters stats;
730 struct pipeline_msg_rsp_table_rule_mtr_read {
731 struct rte_table_action_mtr_counters stats;
734 struct pipeline_msg_rsp_table_rule_ttl_read {
735 struct rte_table_action_ttl_counters stats;
738 struct pipeline_msg_rsp {
743 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
744 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
745 struct pipeline_msg_rsp_table_stats_read table_stats_read;
746 struct pipeline_msg_rsp_table_rule_add table_rule_add;
747 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
748 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
749 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
750 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
751 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
758 static struct pipeline_msg_req *
759 pipeline_msg_alloc(void)
761 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
762 sizeof(struct pipeline_msg_rsp));
764 return calloc(1, size);
768 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
773 static struct pipeline_msg_rsp *
774 pipeline_msg_send_recv(struct pipeline *p,
775 struct pipeline_msg_req *req)
777 struct rte_ring *msgq_req = p->msgq_req;
778 struct rte_ring *msgq_rsp = p->msgq_rsp;
779 struct pipeline_msg_rsp *rsp;
784 status = rte_ring_sp_enqueue(msgq_req, req);
785 } while (status == -ENOBUFS);
789 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
790 } while (status != 0);
796 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
797 const char *pipeline_name,
799 struct rte_pipeline_port_in_stats *stats,
803 struct pipeline_msg_req *req;
804 struct pipeline_msg_rsp *rsp;
807 /* Check input params */
808 if (pipeline_name == NULL ||
812 p = softnic_pipeline_find(softnic, pipeline_name);
814 port_id >= p->n_ports_in)
817 if (!pipeline_is_running(p)) {
818 status = rte_pipeline_port_in_stats_read(p->p,
826 /* Allocate request */
827 req = pipeline_msg_alloc();
832 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
834 req->port_in_stats_read.clear = clear;
836 /* Send request and wait for response */
837 rsp = pipeline_msg_send_recv(p, req);
842 status = rsp->status;
844 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
847 pipeline_msg_free(rsp);
853 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
854 const char *pipeline_name,
858 struct pipeline_msg_req *req;
859 struct pipeline_msg_rsp *rsp;
862 /* Check input params */
863 if (pipeline_name == NULL)
866 p = softnic_pipeline_find(softnic, pipeline_name);
868 port_id >= p->n_ports_in)
871 if (!pipeline_is_running(p)) {
872 status = rte_pipeline_port_in_enable(p->p, port_id);
876 /* Allocate request */
877 req = pipeline_msg_alloc();
882 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
885 /* Send request and wait for response */
886 rsp = pipeline_msg_send_recv(p, req);
891 status = rsp->status;
894 pipeline_msg_free(rsp);
900 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
901 const char *pipeline_name,
905 struct pipeline_msg_req *req;
906 struct pipeline_msg_rsp *rsp;
909 /* Check input params */
910 if (pipeline_name == NULL)
913 p = softnic_pipeline_find(softnic, pipeline_name);
915 port_id >= p->n_ports_in)
918 if (!pipeline_is_running(p)) {
919 status = rte_pipeline_port_in_disable(p->p, port_id);
923 /* Allocate request */
924 req = pipeline_msg_alloc();
929 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
932 /* Send request and wait for response */
933 rsp = pipeline_msg_send_recv(p, req);
938 status = rsp->status;
941 pipeline_msg_free(rsp);
947 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
948 const char *pipeline_name,
950 struct rte_pipeline_port_out_stats *stats,
954 struct pipeline_msg_req *req;
955 struct pipeline_msg_rsp *rsp;
958 /* Check input params */
959 if (pipeline_name == NULL ||
963 p = softnic_pipeline_find(softnic, pipeline_name);
965 port_id >= p->n_ports_out)
968 if (!pipeline_is_running(p)) {
969 status = rte_pipeline_port_out_stats_read(p->p,
977 /* Allocate request */
978 req = pipeline_msg_alloc();
983 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
985 req->port_out_stats_read.clear = clear;
987 /* Send request and wait for response */
988 rsp = pipeline_msg_send_recv(p, req);
993 status = rsp->status;
995 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
998 pipeline_msg_free(rsp);
1004 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
1005 const char *pipeline_name,
1007 struct rte_pipeline_table_stats *stats,
1011 struct pipeline_msg_req *req;
1012 struct pipeline_msg_rsp *rsp;
1015 /* Check input params */
1016 if (pipeline_name == NULL ||
1020 p = softnic_pipeline_find(softnic, pipeline_name);
1022 table_id >= p->n_tables)
1025 if (!pipeline_is_running(p)) {
1026 status = rte_pipeline_table_stats_read(p->p,
1034 /* Allocate request */
1035 req = pipeline_msg_alloc();
1040 req->type = PIPELINE_REQ_TABLE_STATS_READ;
1042 req->table_stats_read.clear = clear;
1044 /* Send request and wait for response */
1045 rsp = pipeline_msg_send_recv(p, req);
1050 status = rsp->status;
1052 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
1055 pipeline_msg_free(rsp);
1061 match_check(struct softnic_table_rule_match *match,
1065 struct softnic_table *table;
1067 if (match == NULL ||
1069 table_id >= p->n_tables)
1072 table = &p->table[table_id];
1073 if (match->match_type != table->params.match_type)
1076 switch (match->match_type) {
1079 struct softnic_table_acl_params *t = &table->params.match.acl;
1080 struct softnic_table_rule_match_acl *r = &match->match.acl;
1082 if ((r->ip_version && (t->ip_version == 0)) ||
1083 ((r->ip_version == 0) && t->ip_version))
1086 if (r->ip_version) {
1087 if (r->sa_depth > 32 ||
1091 if (r->sa_depth > 128 ||
1106 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1107 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1109 if ((r->ip_version && (t->key_size != 4)) ||
1110 ((r->ip_version == 0) && (t->key_size != 16)))
1113 if (r->ip_version) {
1132 action_check(struct softnic_table_rule_action *action,
1136 struct softnic_table_action_profile *ap;
1138 if (action == NULL ||
1140 table_id >= p->n_tables)
1143 ap = p->table[table_id].ap;
1144 if (action->action_mask != ap->params.action_mask)
1147 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1148 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1149 action->fwd.id >= p->n_ports_out)
1152 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1153 action->fwd.id >= p->n_tables)
1157 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1158 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1159 uint32_t tc_mask1 = action->mtr.tc_mask;
1161 if (tc_mask1 != tc_mask0)
1165 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1166 uint32_t n_subports_per_port =
1167 ap->params.tm.n_subports_per_port;
1168 uint32_t n_pipes_per_subport =
1169 ap->params.tm.n_pipes_per_subport;
1170 uint32_t subport_id = action->tm.subport_id;
1171 uint32_t pipe_id = action->tm.pipe_id;
1173 if (subport_id >= n_subports_per_port ||
1174 pipe_id >= n_pipes_per_subport)
1178 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1179 uint64_t encap_mask = ap->params.encap.encap_mask;
1180 enum rte_table_action_encap_type type = action->encap.type;
1182 if ((encap_mask & (1LLU << type)) == 0)
1186 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1187 int ip_version0 = ap->params.common.ip_version;
1188 int ip_version1 = action->nat.ip_version;
1190 if ((ip_version1 && (ip_version0 == 0)) ||
1191 ((ip_version1 == 0) && ip_version0))
1199 action_default_check(struct softnic_table_rule_action *action,
1203 if (action == NULL ||
1204 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1206 table_id >= p->n_tables)
1209 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1210 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1211 action->fwd.id >= p->n_ports_out)
1214 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1215 action->fwd.id >= p->n_tables)
1222 union table_rule_match_low_level {
1223 struct rte_table_acl_rule_add_params acl_add;
1224 struct rte_table_acl_rule_delete_params acl_delete;
1225 struct rte_table_array_key array;
1226 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1227 struct rte_table_lpm_key lpm_ipv4;
1228 struct rte_table_lpm_ipv6_key lpm_ipv6;
1232 match_convert(struct softnic_table_rule_match *mh,
1233 union table_rule_match_low_level *ml,
1237 action_convert(struct rte_table_action *a,
1238 struct softnic_table_rule_action *action,
1239 struct rte_pipeline_table_entry *data);
1242 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1243 const char *pipeline_name,
1245 struct softnic_table_rule_match *match,
1246 struct softnic_table_rule_action *action,
1250 struct pipeline_msg_req *req;
1251 struct pipeline_msg_rsp *rsp;
1254 /* Check input params */
1255 if (pipeline_name == NULL ||
1261 p = softnic_pipeline_find(softnic, pipeline_name);
1263 table_id >= p->n_tables ||
1264 match_check(match, p, table_id) ||
1265 action_check(action, p, table_id))
1268 if (!pipeline_is_running(p)) {
1269 struct rte_table_action *a = p->table[table_id].a;
1270 union table_rule_match_low_level match_ll;
1271 struct rte_pipeline_table_entry *data_in, *data_out;
1275 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1279 /* Table match-action rule conversion */
1280 data_in = (struct rte_pipeline_table_entry *)buffer;
1282 status = match_convert(match, &match_ll, 1);
1288 status = action_convert(a, action, data_in);
1294 /* Add rule (match, action) to table */
1295 status = rte_pipeline_table_entry_add(p->p,
1306 /* Write Response */
1313 /* Allocate request */
1314 req = pipeline_msg_alloc();
1319 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1321 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1322 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1324 /* Send request and wait for response */
1325 rsp = pipeline_msg_send_recv(p, req);
1330 status = rsp->status;
1332 *data = rsp->table_rule_add.data;
1335 pipeline_msg_free(rsp);
1341 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1342 const char *pipeline_name,
1344 struct softnic_table_rule_action *action,
1348 struct pipeline_msg_req *req;
1349 struct pipeline_msg_rsp *rsp;
1352 /* Check input params */
1353 if (pipeline_name == NULL ||
1358 p = softnic_pipeline_find(softnic, pipeline_name);
1360 table_id >= p->n_tables ||
1361 action_default_check(action, p, table_id))
1364 if (!pipeline_is_running(p)) {
1365 struct rte_pipeline_table_entry *data_in, *data_out;
1368 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1373 data_in = (struct rte_pipeline_table_entry *)buffer;
1375 data_in->action = action->fwd.action;
1376 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1377 data_in->port_id = action->fwd.id;
1378 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1379 data_in->table_id = action->fwd.id;
1381 /* Add default rule to table */
1382 status = rte_pipeline_table_default_entry_add(p->p,
1391 /* Write Response */
1398 /* Allocate request */
1399 req = pipeline_msg_alloc();
1404 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1406 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1408 /* Send request and wait for response */
1409 rsp = pipeline_msg_send_recv(p, req);
1414 status = rsp->status;
1416 *data = rsp->table_rule_add_default.data;
1419 pipeline_msg_free(rsp);
1425 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1426 const char *pipeline_name,
1428 struct softnic_table_rule_match *match,
1429 struct softnic_table_rule_action *action,
1434 struct pipeline_msg_req *req;
1435 struct pipeline_msg_rsp *rsp;
1439 /* Check input params */
1440 if (pipeline_name == NULL ||
1448 p = softnic_pipeline_find(softnic, pipeline_name);
1450 table_id >= p->n_tables)
1453 for (i = 0; i < *n_rules; i++)
1454 if (match_check(match, p, table_id) ||
1455 action_check(action, p, table_id))
1458 if (!pipeline_is_running(p)) {
1459 struct rte_table_action *a = p->table[table_id].a;
1460 union table_rule_match_low_level *match_ll;
1462 void **match_ll_ptr;
1463 struct rte_pipeline_table_entry **action_ll_ptr;
1464 struct rte_pipeline_table_entry **entries_ptr =
1465 (struct rte_pipeline_table_entry **)data;
1467 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1470 /* Memory allocation */
1471 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1472 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1473 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1475 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1476 found = calloc(*n_rules, sizeof(int));
1478 if (match_ll == NULL ||
1479 action_ll == NULL ||
1480 match_ll_ptr == NULL ||
1481 action_ll_ptr == NULL ||
1485 for (i = 0; i < *n_rules; i++) {
1486 match_ll_ptr[i] = (void *)&match_ll[i];
1488 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1491 /* Rule match conversion */
1492 for (i = 0; i < *n_rules; i++) {
1493 status = match_convert(&match[i], match_ll_ptr[i], 1);
1498 /* Rule action conversion */
1499 for (i = 0; i < *n_rules; i++) {
1500 status = action_convert(a, &action[i], action_ll_ptr[i]);
1505 /* Add rule (match, action) to table */
1507 status = rte_pipeline_table_entry_add_bulk(p->p,
1517 for (i = 0; i < *n_rules; i++) {
1518 status = rte_pipeline_table_entry_add(p->p,
1533 free(action_ll_ptr);
1542 free(action_ll_ptr);
1551 /* Allocate request */
1552 req = pipeline_msg_alloc();
1557 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1559 req->table_rule_add_bulk.match = match;
1560 req->table_rule_add_bulk.action = action;
1561 req->table_rule_add_bulk.data = data;
1562 req->table_rule_add_bulk.n_rules = *n_rules;
1563 req->table_rule_add_bulk.bulk =
1564 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1566 /* Send request and wait for response */
1567 rsp = pipeline_msg_send_recv(p, req);
1572 status = rsp->status;
1574 *n_rules = rsp->table_rule_add_bulk.n_rules;
1577 pipeline_msg_free(rsp);
1583 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1584 const char *pipeline_name,
1586 struct softnic_table_rule_match *match)
1589 struct pipeline_msg_req *req;
1590 struct pipeline_msg_rsp *rsp;
1593 /* Check input params */
1594 if (pipeline_name == NULL ||
1598 p = softnic_pipeline_find(softnic, pipeline_name);
1600 table_id >= p->n_tables ||
1601 match_check(match, p, table_id))
1604 if (!pipeline_is_running(p)) {
1605 union table_rule_match_low_level match_ll;
1608 status = match_convert(match, &match_ll, 0);
1612 status = rte_pipeline_table_entry_delete(p->p,
1621 /* Allocate request */
1622 req = pipeline_msg_alloc();
1627 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1629 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1631 /* Send request and wait for response */
1632 rsp = pipeline_msg_send_recv(p, req);
1637 status = rsp->status;
1640 pipeline_msg_free(rsp);
1646 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1647 const char *pipeline_name,
1651 struct pipeline_msg_req *req;
1652 struct pipeline_msg_rsp *rsp;
1655 /* Check input params */
1656 if (pipeline_name == NULL)
1659 p = softnic_pipeline_find(softnic, pipeline_name);
1661 table_id >= p->n_tables)
1664 if (!pipeline_is_running(p)) {
1665 status = rte_pipeline_table_default_entry_delete(p->p,
1672 /* Allocate request */
1673 req = pipeline_msg_alloc();
1678 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1681 /* Send request and wait for response */
1682 rsp = pipeline_msg_send_recv(p, req);
1687 status = rsp->status;
1690 pipeline_msg_free(rsp);
1696 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1697 const char *pipeline_name,
1700 struct rte_table_action_stats_counters *stats,
1704 struct pipeline_msg_req *req;
1705 struct pipeline_msg_rsp *rsp;
1708 /* Check input params */
1709 if (pipeline_name == NULL ||
1714 p = softnic_pipeline_find(softnic, pipeline_name);
1716 table_id >= p->n_tables)
1719 if (!pipeline_is_running(p)) {
1720 struct rte_table_action *a = p->table[table_id].a;
1722 status = rte_table_action_stats_read(a,
1730 /* Allocate request */
1731 req = pipeline_msg_alloc();
1736 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1738 req->table_rule_stats_read.data = data;
1739 req->table_rule_stats_read.clear = clear;
1741 /* Send request and wait for response */
1742 rsp = pipeline_msg_send_recv(p, req);
1747 status = rsp->status;
1749 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1752 pipeline_msg_free(rsp);
1758 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1759 const char *pipeline_name,
1761 uint32_t meter_profile_id,
1762 struct rte_table_action_meter_profile *profile)
1765 struct pipeline_msg_req *req;
1766 struct pipeline_msg_rsp *rsp;
1767 struct softnic_table *table;
1768 struct softnic_table_meter_profile *mp;
1771 /* Check input params */
1772 if (pipeline_name == NULL ||
1776 p = softnic_pipeline_find(softnic, pipeline_name);
1778 table_id >= p->n_tables)
1781 table = &p->table[table_id];
1782 mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
1786 /* Resource Allocation */
1787 mp = calloc(1, sizeof(struct softnic_table_meter_profile));
1791 mp->meter_profile_id = meter_profile_id;
1792 memcpy(&mp->profile, profile, sizeof(mp->profile));
1794 if (!pipeline_is_running(p)) {
1795 status = rte_table_action_meter_profile_add(table->a,
1803 /* Add profile to the table. */
1804 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1809 /* Allocate request */
1810 req = pipeline_msg_alloc();
1817 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1819 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1820 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1822 /* Send request and wait for response */
1823 rsp = pipeline_msg_send_recv(p, req);
1830 status = rsp->status;
1832 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1837 pipeline_msg_free(rsp);
1843 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1844 const char *pipeline_name,
1846 uint32_t meter_profile_id)
1849 struct pipeline_msg_req *req;
1850 struct pipeline_msg_rsp *rsp;
1853 /* Check input params */
1854 if (pipeline_name == NULL)
1857 p = softnic_pipeline_find(softnic, pipeline_name);
1859 table_id >= p->n_tables)
1862 if (!pipeline_is_running(p)) {
1863 struct rte_table_action *a = p->table[table_id].a;
1865 status = rte_table_action_meter_profile_delete(a,
1871 /* Allocate request */
1872 req = pipeline_msg_alloc();
1877 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1879 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1881 /* Send request and wait for response */
1882 rsp = pipeline_msg_send_recv(p, req);
1887 status = rsp->status;
1890 pipeline_msg_free(rsp);
1896 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1897 const char *pipeline_name,
1901 struct rte_table_action_mtr_counters *stats,
1905 struct pipeline_msg_req *req;
1906 struct pipeline_msg_rsp *rsp;
1909 /* Check input params */
1910 if (pipeline_name == NULL ||
1915 p = softnic_pipeline_find(softnic, pipeline_name);
1917 table_id >= p->n_tables)
1920 if (!pipeline_is_running(p)) {
1921 struct rte_table_action *a = p->table[table_id].a;
1923 status = rte_table_action_meter_read(a,
1932 /* Allocate request */
1933 req = pipeline_msg_alloc();
1938 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1940 req->table_rule_mtr_read.data = data;
1941 req->table_rule_mtr_read.tc_mask = tc_mask;
1942 req->table_rule_mtr_read.clear = clear;
1944 /* Send request and wait for response */
1945 rsp = pipeline_msg_send_recv(p, req);
1950 status = rsp->status;
1952 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1955 pipeline_msg_free(rsp);
1961 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1962 const char *pipeline_name,
1965 struct rte_table_action_dscp_table *dscp_table)
1968 struct pipeline_msg_req *req;
1969 struct pipeline_msg_rsp *rsp;
1972 /* Check input params */
1973 if (pipeline_name == NULL ||
1977 p = softnic_pipeline_find(softnic, pipeline_name);
1979 table_id >= p->n_tables)
1982 if (!pipeline_is_running(p)) {
1983 struct rte_table_action *a = p->table[table_id].a;
1985 status = rte_table_action_dscp_table_update(a,
1989 /* Update table dscp table */
1991 memcpy(&p->table[table_id].dscp_table, dscp_table,
1992 sizeof(p->table[table_id].dscp_table));
1997 /* Allocate request */
1998 req = pipeline_msg_alloc();
2003 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
2005 req->table_dscp_table_update.dscp_mask = dscp_mask;
2006 memcpy(&req->table_dscp_table_update.dscp_table,
2007 dscp_table, sizeof(*dscp_table));
2009 /* Send request and wait for response */
2010 rsp = pipeline_msg_send_recv(p, req);
2015 status = rsp->status;
2017 /* Update table dscp table */
2019 memcpy(&p->table[table_id].dscp_table, dscp_table,
2020 sizeof(p->table[table_id].dscp_table));
2023 pipeline_msg_free(rsp);
2029 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
2030 const char *pipeline_name,
2033 struct rte_table_action_ttl_counters *stats,
2037 struct pipeline_msg_req *req;
2038 struct pipeline_msg_rsp *rsp;
2041 /* Check input params */
2042 if (pipeline_name == NULL ||
2047 p = softnic_pipeline_find(softnic, pipeline_name);
2049 table_id >= p->n_tables)
2052 if (!pipeline_is_running(p)) {
2053 struct rte_table_action *a = p->table[table_id].a;
2055 status = rte_table_action_ttl_read(a,
2063 /* Allocate request */
2064 req = pipeline_msg_alloc();
2069 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
2071 req->table_rule_ttl_read.data = data;
2072 req->table_rule_ttl_read.clear = clear;
2074 /* Send request and wait for response */
2075 rsp = pipeline_msg_send_recv(p, req);
2080 status = rsp->status;
2082 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2085 pipeline_msg_free(rsp);
2091 * Data plane threads: message handling
2093 static inline struct pipeline_msg_req *
2094 pipeline_msg_recv(struct rte_ring *msgq_req)
2096 struct pipeline_msg_req *req;
2098 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2107 pipeline_msg_send(struct rte_ring *msgq_rsp,
2108 struct pipeline_msg_rsp *rsp)
2113 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2114 } while (status == -ENOBUFS);
2117 static struct pipeline_msg_rsp *
2118 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2119 struct pipeline_msg_req *req)
2121 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2122 uint32_t port_id = req->id;
2123 int clear = req->port_in_stats_read.clear;
2125 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2127 &rsp->port_in_stats_read.stats,
2133 static struct pipeline_msg_rsp *
2134 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2135 struct pipeline_msg_req *req)
2137 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2138 uint32_t port_id = req->id;
2140 rsp->status = rte_pipeline_port_in_enable(p->p,
2146 static struct pipeline_msg_rsp *
2147 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2148 struct pipeline_msg_req *req)
2150 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2151 uint32_t port_id = req->id;
2153 rsp->status = rte_pipeline_port_in_disable(p->p,
2159 static struct pipeline_msg_rsp *
2160 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2161 struct pipeline_msg_req *req)
2163 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2164 uint32_t port_id = req->id;
2165 int clear = req->port_out_stats_read.clear;
2167 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2169 &rsp->port_out_stats_read.stats,
2175 static struct pipeline_msg_rsp *
2176 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2177 struct pipeline_msg_req *req)
2179 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2180 uint32_t port_id = req->id;
2181 int clear = req->table_stats_read.clear;
2183 rsp->status = rte_pipeline_table_stats_read(p->p,
2185 &rsp->table_stats_read.stats,
2192 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2197 switch (depth / 32) {
2207 depth32[1] = depth - 32;
2215 depth32[2] = depth - 64;
2223 depth32[3] = depth - 96;
2239 match_convert(struct softnic_table_rule_match *mh,
2240 union table_rule_match_low_level *ml,
2243 memset(ml, 0, sizeof(*ml));
2245 switch (mh->match_type) {
2247 if (mh->match.acl.ip_version)
2249 ml->acl_add.field_value[0].value.u8 =
2250 mh->match.acl.proto;
2251 ml->acl_add.field_value[0].mask_range.u8 =
2252 mh->match.acl.proto_mask;
2254 ml->acl_add.field_value[1].value.u32 =
2255 mh->match.acl.ipv4.sa;
2256 ml->acl_add.field_value[1].mask_range.u32 =
2257 mh->match.acl.sa_depth;
2259 ml->acl_add.field_value[2].value.u32 =
2260 mh->match.acl.ipv4.da;
2261 ml->acl_add.field_value[2].mask_range.u32 =
2262 mh->match.acl.da_depth;
2264 ml->acl_add.field_value[3].value.u16 =
2266 ml->acl_add.field_value[3].mask_range.u16 =
2269 ml->acl_add.field_value[4].value.u16 =
2271 ml->acl_add.field_value[4].mask_range.u16 =
2274 ml->acl_add.priority =
2275 (int32_t)mh->match.acl.priority;
2277 ml->acl_delete.field_value[0].value.u8 =
2278 mh->match.acl.proto;
2279 ml->acl_delete.field_value[0].mask_range.u8 =
2280 mh->match.acl.proto_mask;
2282 ml->acl_delete.field_value[1].value.u32 =
2283 mh->match.acl.ipv4.sa;
2284 ml->acl_delete.field_value[1].mask_range.u32 =
2285 mh->match.acl.sa_depth;
2287 ml->acl_delete.field_value[2].value.u32 =
2288 mh->match.acl.ipv4.da;
2289 ml->acl_delete.field_value[2].mask_range.u32 =
2290 mh->match.acl.da_depth;
2292 ml->acl_delete.field_value[3].value.u16 =
2294 ml->acl_delete.field_value[3].mask_range.u16 =
2297 ml->acl_delete.field_value[4].value.u16 =
2299 ml->acl_delete.field_value[4].mask_range.u16 =
2305 (uint32_t *)mh->match.acl.ipv6.sa;
2307 (uint32_t *)mh->match.acl.ipv6.da;
2308 uint32_t sa32_depth[4], da32_depth[4];
2311 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2316 status = match_convert_ipv6_depth(
2317 mh->match.acl.da_depth,
2322 ml->acl_add.field_value[0].value.u8 =
2323 mh->match.acl.proto;
2324 ml->acl_add.field_value[0].mask_range.u8 =
2325 mh->match.acl.proto_mask;
2327 ml->acl_add.field_value[1].value.u32 =
2328 rte_be_to_cpu_32(sa32[0]);
2329 ml->acl_add.field_value[1].mask_range.u32 =
2331 ml->acl_add.field_value[2].value.u32 =
2332 rte_be_to_cpu_32(sa32[1]);
2333 ml->acl_add.field_value[2].mask_range.u32 =
2335 ml->acl_add.field_value[3].value.u32 =
2336 rte_be_to_cpu_32(sa32[2]);
2337 ml->acl_add.field_value[3].mask_range.u32 =
2339 ml->acl_add.field_value[4].value.u32 =
2340 rte_be_to_cpu_32(sa32[3]);
2341 ml->acl_add.field_value[4].mask_range.u32 =
2344 ml->acl_add.field_value[5].value.u32 =
2345 rte_be_to_cpu_32(da32[0]);
2346 ml->acl_add.field_value[5].mask_range.u32 =
2348 ml->acl_add.field_value[6].value.u32 =
2349 rte_be_to_cpu_32(da32[1]);
2350 ml->acl_add.field_value[6].mask_range.u32 =
2352 ml->acl_add.field_value[7].value.u32 =
2353 rte_be_to_cpu_32(da32[2]);
2354 ml->acl_add.field_value[7].mask_range.u32 =
2356 ml->acl_add.field_value[8].value.u32 =
2357 rte_be_to_cpu_32(da32[3]);
2358 ml->acl_add.field_value[8].mask_range.u32 =
2361 ml->acl_add.field_value[9].value.u16 =
2363 ml->acl_add.field_value[9].mask_range.u16 =
2366 ml->acl_add.field_value[10].value.u16 =
2368 ml->acl_add.field_value[10].mask_range.u16 =
2371 ml->acl_add.priority =
2372 (int32_t)mh->match.acl.priority;
2375 (uint32_t *)mh->match.acl.ipv6.sa;
2377 (uint32_t *)mh->match.acl.ipv6.da;
2378 uint32_t sa32_depth[4], da32_depth[4];
2381 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2386 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2391 ml->acl_delete.field_value[0].value.u8 =
2392 mh->match.acl.proto;
2393 ml->acl_delete.field_value[0].mask_range.u8 =
2394 mh->match.acl.proto_mask;
2396 ml->acl_delete.field_value[1].value.u32 =
2397 rte_be_to_cpu_32(sa32[0]);
2398 ml->acl_delete.field_value[1].mask_range.u32 =
2400 ml->acl_delete.field_value[2].value.u32 =
2401 rte_be_to_cpu_32(sa32[1]);
2402 ml->acl_delete.field_value[2].mask_range.u32 =
2404 ml->acl_delete.field_value[3].value.u32 =
2405 rte_be_to_cpu_32(sa32[2]);
2406 ml->acl_delete.field_value[3].mask_range.u32 =
2408 ml->acl_delete.field_value[4].value.u32 =
2409 rte_be_to_cpu_32(sa32[3]);
2410 ml->acl_delete.field_value[4].mask_range.u32 =
2413 ml->acl_delete.field_value[5].value.u32 =
2414 rte_be_to_cpu_32(da32[0]);
2415 ml->acl_delete.field_value[5].mask_range.u32 =
2417 ml->acl_delete.field_value[6].value.u32 =
2418 rte_be_to_cpu_32(da32[1]);
2419 ml->acl_delete.field_value[6].mask_range.u32 =
2421 ml->acl_delete.field_value[7].value.u32 =
2422 rte_be_to_cpu_32(da32[2]);
2423 ml->acl_delete.field_value[7].mask_range.u32 =
2425 ml->acl_delete.field_value[8].value.u32 =
2426 rte_be_to_cpu_32(da32[3]);
2427 ml->acl_delete.field_value[8].mask_range.u32 =
2430 ml->acl_delete.field_value[9].value.u16 =
2432 ml->acl_delete.field_value[9].mask_range.u16 =
2435 ml->acl_delete.field_value[10].value.u16 =
2437 ml->acl_delete.field_value[10].mask_range.u16 =
2443 ml->array.pos = mh->match.array.pos;
2447 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2451 if (mh->match.lpm.ip_version) {
2452 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2453 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2455 memcpy(ml->lpm_ipv6.ip,
2456 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2457 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2468 action_convert(struct rte_table_action *a,
2469 struct softnic_table_rule_action *action,
2470 struct rte_pipeline_table_entry *data)
2475 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2476 status = rte_table_action_apply(a,
2478 RTE_TABLE_ACTION_FWD,
2485 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2486 status = rte_table_action_apply(a,
2488 RTE_TABLE_ACTION_LB,
2495 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2496 status = rte_table_action_apply(a,
2498 RTE_TABLE_ACTION_MTR,
2505 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2506 status = rte_table_action_apply(a,
2508 RTE_TABLE_ACTION_TM,
2515 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2516 status = rte_table_action_apply(a,
2518 RTE_TABLE_ACTION_ENCAP,
2525 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2526 status = rte_table_action_apply(a,
2528 RTE_TABLE_ACTION_NAT,
2535 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2536 status = rte_table_action_apply(a,
2538 RTE_TABLE_ACTION_TTL,
2545 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2546 status = rte_table_action_apply(a,
2548 RTE_TABLE_ACTION_STATS,
2555 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2556 status = rte_table_action_apply(a,
2558 RTE_TABLE_ACTION_TIME,
2565 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2566 status = rte_table_action_apply(a,
2568 RTE_TABLE_ACTION_TAG,
2575 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2576 status = rte_table_action_apply(a,
2578 RTE_TABLE_ACTION_DECAP,
2585 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2586 status = rte_table_action_apply(a,
2588 RTE_TABLE_ACTION_SYM_CRYPTO,
2589 &action->sym_crypto);
2598 static struct pipeline_msg_rsp *
2599 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2600 struct pipeline_msg_req *req)
2602 union table_rule_match_low_level match_ll;
2603 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2604 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2605 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2606 struct rte_pipeline_table_entry *data_in, *data_out;
2607 uint32_t table_id = req->id;
2608 int key_found, status;
2609 struct rte_table_action *a = p->table_data[table_id].a;
2612 memset(p->buffer, 0, sizeof(p->buffer));
2613 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2615 status = match_convert(match, &match_ll, 1);
2621 status = action_convert(a, action, data_in);
2627 status = rte_pipeline_table_entry_add(p->p,
2638 /* Write response */
2640 rsp->table_rule_add.data = data_out;
2645 static struct pipeline_msg_rsp *
2646 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2647 struct pipeline_msg_req *req)
2649 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2650 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2651 struct rte_pipeline_table_entry *data_in, *data_out;
2652 uint32_t table_id = req->id;
2656 memset(p->buffer, 0, sizeof(p->buffer));
2657 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2659 data_in->action = action->fwd.action;
2660 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2661 data_in->port_id = action->fwd.id;
2662 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2663 data_in->table_id = action->fwd.id;
2665 /* Add default rule to table */
2666 status = rte_pipeline_table_default_entry_add(p->p,
2675 /* Write response */
2677 rsp->table_rule_add_default.data = data_out;
2682 static struct pipeline_msg_rsp *
2683 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2684 struct pipeline_msg_req *req)
2686 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2688 uint32_t table_id = req->id;
2689 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2690 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2691 struct rte_pipeline_table_entry **data =
2692 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2693 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2694 uint32_t bulk = req->table_rule_add_bulk.bulk;
2696 struct rte_table_action *a = p->table_data[table_id].a;
2697 union table_rule_match_low_level *match_ll;
2699 void **match_ll_ptr;
2700 struct rte_pipeline_table_entry **action_ll_ptr;
2704 /* Memory allocation */
2705 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2706 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2707 match_ll_ptr = calloc(n_rules, sizeof(void *));
2709 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2710 found = calloc(n_rules, sizeof(int));
2712 if (match_ll == NULL ||
2713 action_ll == NULL ||
2714 match_ll_ptr == NULL ||
2715 action_ll_ptr == NULL ||
2719 for (i = 0; i < n_rules; i++) {
2720 match_ll_ptr[i] = (void *)&match_ll[i];
2722 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2725 /* Rule match conversion */
2726 for (i = 0; i < n_rules; i++) {
2727 status = match_convert(&match[i], match_ll_ptr[i], 1);
2732 /* Rule action conversion */
2733 for (i = 0; i < n_rules; i++) {
2734 status = action_convert(a, &action[i], action_ll_ptr[i]);
2739 /* Add rule (match, action) to table */
2741 status = rte_pipeline_table_entry_add_bulk(p->p,
2751 for (i = 0; i < n_rules; i++) {
2752 status = rte_pipeline_table_entry_add(p->p,
2765 /* Write response */
2767 rsp->table_rule_add_bulk.n_rules = n_rules;
2771 free(action_ll_ptr);
2780 free(action_ll_ptr);
2786 rsp->table_rule_add_bulk.n_rules = 0;
2790 static struct pipeline_msg_rsp *
2791 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2792 struct pipeline_msg_req *req)
2794 union table_rule_match_low_level match_ll;
2795 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2796 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2797 uint32_t table_id = req->id;
2798 int key_found, status;
2800 status = match_convert(match, &match_ll, 0);
2806 rsp->status = rte_pipeline_table_entry_delete(p->p,
2815 static struct pipeline_msg_rsp *
2816 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2817 struct pipeline_msg_req *req)
2819 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2820 uint32_t table_id = req->id;
2822 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2829 static struct pipeline_msg_rsp *
2830 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2831 struct pipeline_msg_req *req)
2833 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2834 uint32_t table_id = req->id;
2835 void *data = req->table_rule_stats_read.data;
2836 int clear = req->table_rule_stats_read.clear;
2837 struct rte_table_action *a = p->table_data[table_id].a;
2839 rsp->status = rte_table_action_stats_read(a,
2841 &rsp->table_rule_stats_read.stats,
2847 static struct pipeline_msg_rsp *
2848 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2849 struct pipeline_msg_req *req)
2851 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2852 uint32_t table_id = req->id;
2853 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2854 struct rte_table_action_meter_profile *profile =
2855 &req->table_mtr_profile_add.profile;
2856 struct rte_table_action *a = p->table_data[table_id].a;
2858 rsp->status = rte_table_action_meter_profile_add(a,
2865 static struct pipeline_msg_rsp *
2866 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2867 struct pipeline_msg_req *req)
2869 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2870 uint32_t table_id = req->id;
2871 uint32_t meter_profile_id =
2872 req->table_mtr_profile_delete.meter_profile_id;
2873 struct rte_table_action *a = p->table_data[table_id].a;
2875 rsp->status = rte_table_action_meter_profile_delete(a,
2881 static struct pipeline_msg_rsp *
2882 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2883 struct pipeline_msg_req *req)
2885 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2886 uint32_t table_id = req->id;
2887 void *data = req->table_rule_mtr_read.data;
2888 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2889 int clear = req->table_rule_mtr_read.clear;
2890 struct rte_table_action *a = p->table_data[table_id].a;
2892 rsp->status = rte_table_action_meter_read(a,
2895 &rsp->table_rule_mtr_read.stats,
2901 static struct pipeline_msg_rsp *
2902 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2903 struct pipeline_msg_req *req)
2905 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2906 uint32_t table_id = req->id;
2907 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2908 struct rte_table_action_dscp_table *dscp_table =
2909 &req->table_dscp_table_update.dscp_table;
2910 struct rte_table_action *a = p->table_data[table_id].a;
2912 rsp->status = rte_table_action_dscp_table_update(a,
2919 static struct pipeline_msg_rsp *
2920 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2921 struct pipeline_msg_req *req)
2923 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2924 uint32_t table_id = req->id;
2925 void *data = req->table_rule_ttl_read.data;
2926 int clear = req->table_rule_ttl_read.clear;
2927 struct rte_table_action *a = p->table_data[table_id].a;
2929 rsp->status = rte_table_action_ttl_read(a,
2931 &rsp->table_rule_ttl_read.stats,
2938 pipeline_msg_handle(struct pipeline_data *p)
2941 struct pipeline_msg_req *req;
2942 struct pipeline_msg_rsp *rsp;
2944 req = pipeline_msg_recv(p->msgq_req);
2948 switch (req->type) {
2949 case PIPELINE_REQ_PORT_IN_STATS_READ:
2950 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2953 case PIPELINE_REQ_PORT_IN_ENABLE:
2954 rsp = pipeline_msg_handle_port_in_enable(p, req);
2957 case PIPELINE_REQ_PORT_IN_DISABLE:
2958 rsp = pipeline_msg_handle_port_in_disable(p, req);
2961 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2962 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2965 case PIPELINE_REQ_TABLE_STATS_READ:
2966 rsp = pipeline_msg_handle_table_stats_read(p, req);
2969 case PIPELINE_REQ_TABLE_RULE_ADD:
2970 rsp = pipeline_msg_handle_table_rule_add(p, req);
2973 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2974 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2977 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2978 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2981 case PIPELINE_REQ_TABLE_RULE_DELETE:
2982 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2985 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2986 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2989 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2990 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2993 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2994 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
2997 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
2998 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
3001 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
3002 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
3005 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
3006 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
3009 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
3010 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
3014 rsp = (struct pipeline_msg_rsp *)req;
3018 pipeline_msg_send(p->msgq_rsp, rsp);
3023 * Data plane threads: main
3026 rte_pmd_softnic_run_internal(void *arg)
3028 struct rte_eth_dev *dev = arg;
3029 struct pmd_internals *softnic;
3030 struct softnic_thread_data *t;
3031 uint32_t thread_id, j;
3033 softnic = dev->data->dev_private;
3034 thread_id = rte_lcore_id();
3035 t = &softnic->thread_data[thread_id];
3039 for (j = 0; j < t->n_pipelines; j++)
3040 rte_pipeline_run(t->p[j]);
3043 if ((t->iter & 0xFLLU) == 0) {
3044 uint64_t time = rte_get_tsc_cycles();
3045 uint64_t time_next_min = UINT64_MAX;
3047 if (time < t->time_next_min)
3050 /* Pipeline message queues */
3051 for (j = 0; j < t->n_pipelines; j++) {
3052 struct pipeline_data *p =
3053 &t->pipeline_data[j];
3054 uint64_t time_next = p->time_next;
3056 if (time_next <= time) {
3057 pipeline_msg_handle(p);
3058 rte_pipeline_flush(p->p);
3059 time_next = time + p->timer_period;
3060 p->time_next = time_next;
3063 if (time_next < time_next_min)
3064 time_next_min = time_next;
3067 /* Thread message queues */
3069 uint64_t time_next = t->time_next;
3071 if (time_next <= time) {
3072 thread_msg_handle(t);
3073 time_next = time + t->timer_period;
3074 t->time_next = time_next;
3077 if (time_next < time_next_min)
3078 time_next_min = time_next;
3081 t->time_next_min = time_next_min;
3088 rte_pmd_softnic_run(uint16_t port_id)
3090 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3092 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
3093 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
3096 return (int)rte_pmd_softnic_run_internal(dev);