1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
7 #include <rte_common.h>
8 #include <rte_cycles.h>
12 #include <rte_table_acl.h>
13 #include <rte_table_array.h>
14 #include <rte_table_hash.h>
15 #include <rte_table_lpm.h>
16 #include <rte_table_lpm_ipv6.h>
17 #include "rte_eth_softnic_internals.h"
20 * Master thread: data plane thread init
23 softnic_thread_free(struct pmd_internals *softnic)
27 RTE_LCORE_FOREACH_SLAVE(i) {
28 struct softnic_thread *t = &softnic->thread[i];
32 rte_ring_free(t->msgq_req);
35 rte_ring_free(t->msgq_rsp);
40 softnic_thread_init(struct pmd_internals *softnic)
44 RTE_LCORE_FOREACH_SLAVE(i) {
45 char ring_name[NAME_MAX];
46 struct rte_ring *msgq_req, *msgq_rsp;
47 struct softnic_thread *t = &softnic->thread[i];
48 struct softnic_thread_data *t_data = &softnic->thread_data[i];
49 uint32_t cpu_id = rte_lcore_to_socket_id(i);
52 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ",
56 msgq_req = rte_ring_create(ring_name,
59 RING_F_SP_ENQ | RING_F_SC_DEQ);
61 if (msgq_req == NULL) {
62 softnic_thread_free(softnic);
66 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP",
70 msgq_rsp = rte_ring_create(ring_name,
73 RING_F_SP_ENQ | RING_F_SC_DEQ);
75 if (msgq_rsp == NULL) {
76 softnic_thread_free(softnic);
80 /* Master thread records */
81 t->msgq_req = msgq_req;
82 t->msgq_rsp = msgq_rsp;
85 /* Data plane thread records */
86 t_data->n_pipelines = 0;
87 t_data->msgq_req = msgq_req;
88 t_data->msgq_rsp = msgq_rsp;
89 t_data->timer_period =
90 (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
91 t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
92 t_data->time_next_min = t_data->time_next;
99 thread_is_running(uint32_t thread_id)
101 enum rte_lcore_state_t thread_state;
103 thread_state = rte_eal_get_lcore_state(thread_id);
104 return (thread_state == RUNNING)? 1 : 0;
108 * Pipeline is running when:
109 * (A) Pipeline is mapped to a data plane thread AND
110 * (B) Its data plane thread is in RUNNING state.
113 pipeline_is_running(struct pipeline *p)
118 return thread_is_running(p->thread_id);
122 * Master thread & data plane threads: message passing
124 enum thread_req_type {
125 THREAD_REQ_PIPELINE_ENABLE = 0,
126 THREAD_REQ_PIPELINE_DISABLE,
130 struct thread_msg_req {
131 enum thread_req_type type;
135 struct rte_pipeline *p;
137 struct rte_table_action *a;
138 } table[RTE_PIPELINE_TABLE_MAX];
139 struct rte_ring *msgq_req;
140 struct rte_ring *msgq_rsp;
141 uint32_t timer_period_ms;
146 struct rte_pipeline *p;
151 struct thread_msg_rsp {
158 static struct thread_msg_req *
159 thread_msg_alloc(void)
161 size_t size = RTE_MAX(sizeof(struct thread_msg_req),
162 sizeof(struct thread_msg_rsp));
164 return calloc(1, size);
168 thread_msg_free(struct thread_msg_rsp *rsp)
173 static struct thread_msg_rsp *
174 thread_msg_send_recv(struct pmd_internals *softnic,
176 struct thread_msg_req *req)
178 struct softnic_thread *t = &softnic->thread[thread_id];
179 struct rte_ring *msgq_req = t->msgq_req;
180 struct rte_ring *msgq_rsp = t->msgq_rsp;
181 struct thread_msg_rsp *rsp;
186 status = rte_ring_sp_enqueue(msgq_req, req);
187 } while (status == -ENOBUFS);
191 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
192 } while (status != 0);
198 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
200 const char *pipeline_name)
202 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
203 struct softnic_thread *t;
204 struct thread_msg_req *req;
205 struct thread_msg_rsp *rsp;
209 /* Check input params */
210 if ((thread_id >= RTE_MAX_LCORE) ||
212 (p->n_ports_in == 0) ||
213 (p->n_ports_out == 0) ||
217 t = &softnic->thread[thread_id];
218 if ((t->enabled == 0) ||
222 if (!thread_is_running(thread_id)) {
223 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
224 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
226 if (td->n_pipelines >= THREAD_PIPELINES_MAX)
229 /* Data plane thread */
230 td->p[td->n_pipelines] = p->p;
233 for (i = 0; i < p->n_tables; i++)
234 tdp->table_data[i].a =
236 tdp->n_tables = p->n_tables;
238 tdp->msgq_req = p->msgq_req;
239 tdp->msgq_rsp = p->msgq_rsp;
240 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
241 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
246 p->thread_id = thread_id;
252 /* Allocate request */
253 req = thread_msg_alloc();
258 req->type = THREAD_REQ_PIPELINE_ENABLE;
259 req->pipeline_enable.p = p->p;
260 for (i = 0; i < p->n_tables; i++)
261 req->pipeline_enable.table[i].a =
263 req->pipeline_enable.msgq_req = p->msgq_req;
264 req->pipeline_enable.msgq_rsp = p->msgq_rsp;
265 req->pipeline_enable.timer_period_ms = p->timer_period_ms;
266 req->pipeline_enable.n_tables = p->n_tables;
268 /* Send request and wait for response */
269 rsp = thread_msg_send_recv(softnic, thread_id, req);
274 status = rsp->status;
277 thread_msg_free(rsp);
279 /* Request completion */
283 p->thread_id = thread_id;
290 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
292 const char *pipeline_name)
294 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
295 struct softnic_thread *t;
296 struct thread_msg_req *req;
297 struct thread_msg_rsp *rsp;
300 /* Check input params */
301 if ((thread_id >= RTE_MAX_LCORE) ||
305 t = &softnic->thread[thread_id];
312 if (p->thread_id != thread_id)
315 if (!thread_is_running(thread_id)) {
316 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
319 for (i = 0; i < td->n_pipelines; i++) {
320 struct pipeline_data *tdp = &td->pipeline_data[i];
325 /* Data plane thread */
326 if (i < td->n_pipelines - 1) {
327 struct rte_pipeline *pipeline_last =
328 td->p[td->n_pipelines - 1];
329 struct pipeline_data *tdp_last =
330 &td->pipeline_data[td->n_pipelines - 1];
332 td->p[i] = pipeline_last;
333 memcpy(tdp, tdp_last, sizeof(*tdp));
347 /* Allocate request */
348 req = thread_msg_alloc();
353 req->type = THREAD_REQ_PIPELINE_DISABLE;
354 req->pipeline_disable.p = p->p;
356 /* Send request and wait for response */
357 rsp = thread_msg_send_recv(softnic, thread_id, req);
362 status = rsp->status;
365 thread_msg_free(rsp);
367 /* Request completion */
377 * Data plane threads: message handling
379 static inline struct thread_msg_req *
380 thread_msg_recv(struct rte_ring *msgq_req)
382 struct thread_msg_req *req;
384 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
393 thread_msg_send(struct rte_ring *msgq_rsp,
394 struct thread_msg_rsp *rsp)
399 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
400 } while (status == -ENOBUFS);
403 static struct thread_msg_rsp *
404 thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
405 struct thread_msg_req *req)
407 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
408 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
412 if (t->n_pipelines >= THREAD_PIPELINES_MAX) {
417 t->p[t->n_pipelines] = req->pipeline_enable.p;
419 p->p = req->pipeline_enable.p;
420 for (i = 0; i < req->pipeline_enable.n_tables; i++)
422 req->pipeline_enable.table[i].a;
424 p->n_tables = req->pipeline_enable.n_tables;
426 p->msgq_req = req->pipeline_enable.msgq_req;
427 p->msgq_rsp = req->pipeline_enable.msgq_rsp;
429 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
430 p->time_next = rte_get_tsc_cycles() + p->timer_period;
439 static struct thread_msg_rsp *
440 thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
441 struct thread_msg_req *req)
443 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
444 uint32_t n_pipelines = t->n_pipelines;
445 struct rte_pipeline *pipeline = req->pipeline_disable.p;
449 for (i = 0; i < n_pipelines; i++) {
450 struct pipeline_data *p = &t->pipeline_data[i];
452 if (p->p != pipeline)
455 if (i < n_pipelines - 1) {
456 struct rte_pipeline *pipeline_last =
457 t->p[n_pipelines - 1];
458 struct pipeline_data *p_last =
459 &t->pipeline_data[n_pipelines - 1];
461 t->p[i] = pipeline_last;
462 memcpy(p, p_last, sizeof(*p));
471 /* should not get here */
477 thread_msg_handle(struct softnic_thread_data *t)
480 struct thread_msg_req *req;
481 struct thread_msg_rsp *rsp;
483 req = thread_msg_recv(t->msgq_req);
488 case THREAD_REQ_PIPELINE_ENABLE:
489 rsp = thread_msg_handle_pipeline_enable(t, req);
492 case THREAD_REQ_PIPELINE_DISABLE:
493 rsp = thread_msg_handle_pipeline_disable(t, req);
497 rsp = (struct thread_msg_rsp *)req;
501 thread_msg_send(t->msgq_rsp, rsp);
506 * Master thread & data plane threads: message passing
508 enum pipeline_req_type {
510 PIPELINE_REQ_PORT_IN_STATS_READ,
511 PIPELINE_REQ_PORT_IN_ENABLE,
512 PIPELINE_REQ_PORT_IN_DISABLE,
515 PIPELINE_REQ_PORT_OUT_STATS_READ,
518 PIPELINE_REQ_TABLE_STATS_READ,
519 PIPELINE_REQ_TABLE_RULE_ADD,
520 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
521 PIPELINE_REQ_TABLE_RULE_ADD_BULK,
522 PIPELINE_REQ_TABLE_RULE_DELETE,
523 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
524 PIPELINE_REQ_TABLE_RULE_STATS_READ,
525 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
526 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
527 PIPELINE_REQ_TABLE_RULE_MTR_READ,
528 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
532 struct pipeline_msg_req_port_in_stats_read {
536 struct pipeline_msg_req_port_out_stats_read {
540 struct pipeline_msg_req_table_stats_read {
544 struct pipeline_msg_req_table_rule_add {
545 struct softnic_table_rule_match match;
546 struct softnic_table_rule_action action;
549 struct pipeline_msg_req_table_rule_add_default {
550 struct softnic_table_rule_action action;
553 struct pipeline_msg_req_table_rule_add_bulk {
554 struct softnic_table_rule_match *match;
555 struct softnic_table_rule_action *action;
561 struct pipeline_msg_req_table_rule_delete {
562 struct softnic_table_rule_match match;
565 struct pipeline_msg_req_table_rule_stats_read {
570 struct pipeline_msg_req_table_mtr_profile_add {
571 uint32_t meter_profile_id;
572 struct rte_table_action_meter_profile profile;
575 struct pipeline_msg_req_table_mtr_profile_delete {
576 uint32_t meter_profile_id;
579 struct pipeline_msg_req_table_rule_mtr_read {
585 struct pipeline_msg_req_table_dscp_table_update {
587 struct rte_table_action_dscp_table dscp_table;
590 struct pipeline_msg_req {
591 enum pipeline_req_type type;
592 uint32_t id; /* Port IN, port OUT or table ID */
596 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
597 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
598 struct pipeline_msg_req_table_stats_read table_stats_read;
599 struct pipeline_msg_req_table_rule_add table_rule_add;
600 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
601 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
602 struct pipeline_msg_req_table_rule_delete table_rule_delete;
603 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
604 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
605 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
606 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
607 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
611 struct pipeline_msg_rsp_port_in_stats_read {
612 struct rte_pipeline_port_in_stats stats;
615 struct pipeline_msg_rsp_port_out_stats_read {
616 struct rte_pipeline_port_out_stats stats;
619 struct pipeline_msg_rsp_table_stats_read {
620 struct rte_pipeline_table_stats stats;
623 struct pipeline_msg_rsp_table_rule_add {
627 struct pipeline_msg_rsp_table_rule_add_default {
631 struct pipeline_msg_rsp_table_rule_add_bulk {
635 struct pipeline_msg_rsp_table_rule_stats_read {
636 struct rte_table_action_stats_counters stats;
639 struct pipeline_msg_rsp_table_rule_mtr_read {
640 struct rte_table_action_mtr_counters stats;
643 struct pipeline_msg_rsp {
648 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
649 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
650 struct pipeline_msg_rsp_table_stats_read table_stats_read;
651 struct pipeline_msg_rsp_table_rule_add table_rule_add;
652 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
653 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
654 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
655 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
662 static struct pipeline_msg_req *
663 pipeline_msg_alloc(void)
665 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
666 sizeof(struct pipeline_msg_rsp));
668 return calloc(1, size);
672 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
677 static struct pipeline_msg_rsp *
678 pipeline_msg_send_recv(struct pipeline *p,
679 struct pipeline_msg_req *req)
681 struct rte_ring *msgq_req = p->msgq_req;
682 struct rte_ring *msgq_rsp = p->msgq_rsp;
683 struct pipeline_msg_rsp *rsp;
688 status = rte_ring_sp_enqueue(msgq_req, req);
689 } while (status == -ENOBUFS);
693 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
694 } while (status != 0);
700 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
701 const char *pipeline_name,
703 struct rte_pipeline_port_in_stats *stats,
707 struct pipeline_msg_req *req;
708 struct pipeline_msg_rsp *rsp;
711 /* Check input params */
712 if (pipeline_name == NULL ||
716 p = softnic_pipeline_find(softnic, pipeline_name);
718 port_id >= p->n_ports_in)
721 if (!pipeline_is_running(p)) {
722 status = rte_pipeline_port_in_stats_read(p->p,
730 /* Allocate request */
731 req = pipeline_msg_alloc();
736 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
738 req->port_in_stats_read.clear = clear;
740 /* Send request and wait for response */
741 rsp = pipeline_msg_send_recv(p, req);
746 status = rsp->status;
748 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
751 pipeline_msg_free(rsp);
757 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
758 const char *pipeline_name,
762 struct pipeline_msg_req *req;
763 struct pipeline_msg_rsp *rsp;
766 /* Check input params */
767 if (pipeline_name == NULL)
770 p = softnic_pipeline_find(softnic, pipeline_name);
772 port_id >= p->n_ports_in)
775 if (!pipeline_is_running(p)) {
776 status = rte_pipeline_port_in_enable(p->p, port_id);
780 /* Allocate request */
781 req = pipeline_msg_alloc();
786 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
789 /* Send request and wait for response */
790 rsp = pipeline_msg_send_recv(p, req);
795 status = rsp->status;
798 pipeline_msg_free(rsp);
804 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
805 const char *pipeline_name,
809 struct pipeline_msg_req *req;
810 struct pipeline_msg_rsp *rsp;
813 /* Check input params */
814 if (pipeline_name == NULL)
817 p = softnic_pipeline_find(softnic, pipeline_name);
819 port_id >= p->n_ports_in)
822 if (!pipeline_is_running(p)) {
823 status = rte_pipeline_port_in_disable(p->p, port_id);
827 /* Allocate request */
828 req = pipeline_msg_alloc();
833 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
836 /* Send request and wait for response */
837 rsp = pipeline_msg_send_recv(p, req);
842 status = rsp->status;
845 pipeline_msg_free(rsp);
851 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
852 const char *pipeline_name,
854 struct rte_pipeline_port_out_stats *stats,
858 struct pipeline_msg_req *req;
859 struct pipeline_msg_rsp *rsp;
862 /* Check input params */
863 if (pipeline_name == NULL ||
867 p = softnic_pipeline_find(softnic, pipeline_name);
869 port_id >= p->n_ports_out)
872 if (!pipeline_is_running(p)) {
873 status = rte_pipeline_port_out_stats_read(p->p,
881 /* Allocate request */
882 req = pipeline_msg_alloc();
887 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
889 req->port_out_stats_read.clear = clear;
891 /* Send request and wait for response */
892 rsp = pipeline_msg_send_recv(p, req);
897 status = rsp->status;
899 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
902 pipeline_msg_free(rsp);
908 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
909 const char *pipeline_name,
911 struct rte_pipeline_table_stats *stats,
915 struct pipeline_msg_req *req;
916 struct pipeline_msg_rsp *rsp;
919 /* Check input params */
920 if (pipeline_name == NULL ||
924 p = softnic_pipeline_find(softnic, pipeline_name);
926 table_id >= p->n_tables)
929 if (!pipeline_is_running(p)) {
930 status = rte_pipeline_table_stats_read(p->p,
938 /* Allocate request */
939 req = pipeline_msg_alloc();
944 req->type = PIPELINE_REQ_TABLE_STATS_READ;
946 req->table_stats_read.clear = clear;
948 /* Send request and wait for response */
949 rsp = pipeline_msg_send_recv(p, req);
954 status = rsp->status;
956 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
959 pipeline_msg_free(rsp);
965 match_check(struct softnic_table_rule_match *match,
969 struct softnic_table *table;
973 table_id >= p->n_tables)
976 table = &p->table[table_id];
977 if (match->match_type != table->params.match_type)
980 switch (match->match_type) {
983 struct softnic_table_acl_params *t = &table->params.match.acl;
984 struct softnic_table_rule_match_acl *r = &match->match.acl;
986 if ((r->ip_version && (t->ip_version == 0)) ||
987 ((r->ip_version == 0) && t->ip_version))
991 if (r->sa_depth > 32 ||
995 if (r->sa_depth > 128 ||
1010 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1011 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1013 if ((r->ip_version && (t->key_size != 4)) ||
1014 ((r->ip_version == 0) && (t->key_size != 16)))
1017 if (r->ip_version) {
1036 action_check(struct softnic_table_rule_action *action,
1040 struct softnic_table_action_profile *ap;
1042 if (action == NULL ||
1044 table_id >= p->n_tables)
1047 ap = p->table[table_id].ap;
1048 if (action->action_mask != ap->params.action_mask)
1051 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1052 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1053 action->fwd.id >= p->n_ports_out)
1056 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1057 action->fwd.id >= p->n_tables)
1061 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1062 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1063 uint32_t tc_mask1 = action->mtr.tc_mask;
1065 if (tc_mask1 != tc_mask0)
1069 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1070 uint32_t n_subports_per_port =
1071 ap->params.tm.n_subports_per_port;
1072 uint32_t n_pipes_per_subport =
1073 ap->params.tm.n_pipes_per_subport;
1074 uint32_t subport_id = action->tm.subport_id;
1075 uint32_t pipe_id = action->tm.pipe_id;
1077 if (subport_id >= n_subports_per_port ||
1078 pipe_id >= n_pipes_per_subport)
1082 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1083 uint64_t encap_mask = ap->params.encap.encap_mask;
1084 enum rte_table_action_encap_type type = action->encap.type;
1086 if ((encap_mask & (1LLU << type)) == 0)
1090 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1091 int ip_version0 = ap->params.common.ip_version;
1092 int ip_version1 = action->nat.ip_version;
1094 if ((ip_version1 && (ip_version0 == 0)) ||
1095 ((ip_version1 == 0) && ip_version0))
1103 action_default_check(struct softnic_table_rule_action *action,
1107 if (action == NULL ||
1108 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1110 table_id >= p->n_tables)
1113 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1114 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1115 action->fwd.id >= p->n_ports_out)
1118 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1119 action->fwd.id >= p->n_tables)
1126 union table_rule_match_low_level {
1127 struct rte_table_acl_rule_add_params acl_add;
1128 struct rte_table_acl_rule_delete_params acl_delete;
1129 struct rte_table_array_key array;
1130 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1131 struct rte_table_lpm_key lpm_ipv4;
1132 struct rte_table_lpm_ipv6_key lpm_ipv6;
1136 match_convert(struct softnic_table_rule_match *mh,
1137 union table_rule_match_low_level *ml,
1141 action_convert(struct rte_table_action *a,
1142 struct softnic_table_rule_action *action,
1143 struct rte_pipeline_table_entry *data);
1146 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1147 const char *pipeline_name,
1149 struct softnic_table_rule_match *match,
1150 struct softnic_table_rule_action *action,
1154 struct pipeline_msg_req *req;
1155 struct pipeline_msg_rsp *rsp;
1158 /* Check input params */
1159 if (pipeline_name == NULL ||
1165 p = softnic_pipeline_find(softnic, pipeline_name);
1167 table_id >= p->n_tables ||
1168 match_check(match, p, table_id) ||
1169 action_check(action, p, table_id))
1172 if (!pipeline_is_running(p)) {
1173 struct rte_table_action *a = p->table[table_id].a;
1174 union table_rule_match_low_level match_ll;
1175 struct rte_pipeline_table_entry *data_in, *data_out;
1179 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1183 /* Table match-action rule conversion */
1184 data_in = (struct rte_pipeline_table_entry *)buffer;
1186 status = match_convert(match, &match_ll, 1);
1192 status = action_convert(a, action, data_in);
1198 /* Add rule (match, action) to table */
1199 status = rte_pipeline_table_entry_add(p->p,
1210 /* Write Response */
1217 /* Allocate request */
1218 req = pipeline_msg_alloc();
1223 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1225 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1226 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1228 /* Send request and wait for response */
1229 rsp = pipeline_msg_send_recv(p, req);
1234 status = rsp->status;
1236 *data = rsp->table_rule_add.data;
1239 pipeline_msg_free(rsp);
1245 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1246 const char *pipeline_name,
1248 struct softnic_table_rule_action *action,
1252 struct pipeline_msg_req *req;
1253 struct pipeline_msg_rsp *rsp;
1256 /* Check input params */
1257 if (pipeline_name == NULL ||
1262 p = softnic_pipeline_find(softnic, pipeline_name);
1264 table_id >= p->n_tables ||
1265 action_default_check(action, p, table_id))
1268 if (!pipeline_is_running(p)) {
1269 struct rte_pipeline_table_entry *data_in, *data_out;
1272 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1277 data_in = (struct rte_pipeline_table_entry *)buffer;
1279 data_in->action = action->fwd.action;
1280 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1281 data_in->port_id = action->fwd.id;
1282 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1283 data_in->table_id = action->fwd.id;
1285 /* Add default rule to table */
1286 status = rte_pipeline_table_default_entry_add(p->p,
1295 /* Write Response */
1302 /* Allocate request */
1303 req = pipeline_msg_alloc();
1308 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1310 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1312 /* Send request and wait for response */
1313 rsp = pipeline_msg_send_recv(p, req);
1318 status = rsp->status;
1320 *data = rsp->table_rule_add_default.data;
1323 pipeline_msg_free(rsp);
1329 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1330 const char *pipeline_name,
1332 struct softnic_table_rule_match *match,
1333 struct softnic_table_rule_action *action,
1338 struct pipeline_msg_req *req;
1339 struct pipeline_msg_rsp *rsp;
1343 /* Check input params */
1344 if (pipeline_name == NULL ||
1352 p = softnic_pipeline_find(softnic, pipeline_name);
1354 table_id >= p->n_tables)
1357 for (i = 0; i < *n_rules; i++)
1358 if (match_check(match, p, table_id) ||
1359 action_check(action, p, table_id))
1362 if (!pipeline_is_running(p)) {
1363 struct rte_table_action *a = p->table[table_id].a;
1364 union table_rule_match_low_level *match_ll;
1366 void **match_ll_ptr;
1367 struct rte_pipeline_table_entry **action_ll_ptr;
1368 struct rte_pipeline_table_entry **entries_ptr =
1369 (struct rte_pipeline_table_entry **)data;
1371 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1374 /* Memory allocation */
1375 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1376 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1377 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1379 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1380 found = calloc(*n_rules, sizeof(int));
1382 if (match_ll == NULL ||
1383 action_ll == NULL ||
1384 match_ll_ptr == NULL ||
1385 action_ll_ptr == NULL ||
1389 for (i = 0; i < *n_rules; i++) {
1390 match_ll_ptr[i] = (void *)&match_ll[i];
1392 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1395 /* Rule match conversion */
1396 for (i = 0; i < *n_rules; i++) {
1397 status = match_convert(&match[i], match_ll_ptr[i], 1);
1402 /* Rule action conversion */
1403 for (i = 0; i < *n_rules; i++) {
1404 status = action_convert(a, &action[i], action_ll_ptr[i]);
1409 /* Add rule (match, action) to table */
1411 status = rte_pipeline_table_entry_add_bulk(p->p,
1421 for (i = 0; i < *n_rules; i++) {
1422 status = rte_pipeline_table_entry_add(p->p,
1437 free(action_ll_ptr);
1446 free(action_ll_ptr);
1455 /* Allocate request */
1456 req = pipeline_msg_alloc();
1461 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1463 req->table_rule_add_bulk.match = match;
1464 req->table_rule_add_bulk.action = action;
1465 req->table_rule_add_bulk.data = data;
1466 req->table_rule_add_bulk.n_rules = *n_rules;
1467 req->table_rule_add_bulk.bulk =
1468 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1470 /* Send request and wait for response */
1471 rsp = pipeline_msg_send_recv(p, req);
1476 status = rsp->status;
1478 *n_rules = rsp->table_rule_add_bulk.n_rules;
1481 pipeline_msg_free(rsp);
1487 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1488 const char *pipeline_name,
1490 struct softnic_table_rule_match *match)
1493 struct pipeline_msg_req *req;
1494 struct pipeline_msg_rsp *rsp;
1497 /* Check input params */
1498 if (pipeline_name == NULL ||
1502 p = softnic_pipeline_find(softnic, pipeline_name);
1504 table_id >= p->n_tables ||
1505 match_check(match, p, table_id))
1508 if (!pipeline_is_running(p)) {
1509 union table_rule_match_low_level match_ll;
1512 status = match_convert(match, &match_ll, 0);
1516 status = rte_pipeline_table_entry_delete(p->p,
1525 /* Allocate request */
1526 req = pipeline_msg_alloc();
1531 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1533 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1535 /* Send request and wait for response */
1536 rsp = pipeline_msg_send_recv(p, req);
1541 status = rsp->status;
1544 pipeline_msg_free(rsp);
1550 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1551 const char *pipeline_name,
1555 struct pipeline_msg_req *req;
1556 struct pipeline_msg_rsp *rsp;
1559 /* Check input params */
1560 if (pipeline_name == NULL)
1563 p = softnic_pipeline_find(softnic, pipeline_name);
1565 table_id >= p->n_tables)
1568 if (!pipeline_is_running(p)) {
1569 status = rte_pipeline_table_default_entry_delete(p->p,
1576 /* Allocate request */
1577 req = pipeline_msg_alloc();
1582 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1585 /* Send request and wait for response */
1586 rsp = pipeline_msg_send_recv(p, req);
1591 status = rsp->status;
1594 pipeline_msg_free(rsp);
1600 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1601 const char *pipeline_name,
1604 struct rte_table_action_stats_counters *stats,
1608 struct pipeline_msg_req *req;
1609 struct pipeline_msg_rsp *rsp;
1612 /* Check input params */
1613 if (pipeline_name == NULL ||
1618 p = softnic_pipeline_find(softnic, pipeline_name);
1620 table_id >= p->n_tables)
1623 if (!pipeline_is_running(p)) {
1624 struct rte_table_action *a = p->table[table_id].a;
1626 status = rte_table_action_stats_read(a,
1634 /* Allocate request */
1635 req = pipeline_msg_alloc();
1640 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1642 req->table_rule_stats_read.data = data;
1643 req->table_rule_stats_read.clear = clear;
1645 /* Send request and wait for response */
1646 rsp = pipeline_msg_send_recv(p, req);
1651 status = rsp->status;
1653 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1656 pipeline_msg_free(rsp);
1662 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1663 const char *pipeline_name,
1665 uint32_t meter_profile_id,
1666 struct rte_table_action_meter_profile *profile)
1669 struct pipeline_msg_req *req;
1670 struct pipeline_msg_rsp *rsp;
1673 /* Check input params */
1674 if (pipeline_name == NULL ||
1678 p = softnic_pipeline_find(softnic, pipeline_name);
1680 table_id >= p->n_tables)
1683 if (!pipeline_is_running(p)) {
1684 struct rte_table_action *a = p->table[table_id].a;
1686 status = rte_table_action_meter_profile_add(a,
1693 /* Allocate request */
1694 req = pipeline_msg_alloc();
1699 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1701 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1702 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1704 /* Send request and wait for response */
1705 rsp = pipeline_msg_send_recv(p, req);
1710 status = rsp->status;
1713 pipeline_msg_free(rsp);
1719 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1720 const char *pipeline_name,
1722 uint32_t meter_profile_id)
1725 struct pipeline_msg_req *req;
1726 struct pipeline_msg_rsp *rsp;
1729 /* Check input params */
1730 if (pipeline_name == NULL)
1733 p = softnic_pipeline_find(softnic, pipeline_name);
1735 table_id >= p->n_tables)
1738 if (!pipeline_is_running(p)) {
1739 struct rte_table_action *a = p->table[table_id].a;
1741 status = rte_table_action_meter_profile_delete(a,
1747 /* Allocate request */
1748 req = pipeline_msg_alloc();
1753 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1755 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1757 /* Send request and wait for response */
1758 rsp = pipeline_msg_send_recv(p, req);
1763 status = rsp->status;
1766 pipeline_msg_free(rsp);
1772 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1773 const char *pipeline_name,
1777 struct rte_table_action_mtr_counters *stats,
1781 struct pipeline_msg_req *req;
1782 struct pipeline_msg_rsp *rsp;
1785 /* Check input params */
1786 if (pipeline_name == NULL ||
1791 p = softnic_pipeline_find(softnic, pipeline_name);
1793 table_id >= p->n_tables)
1796 if (!pipeline_is_running(p)) {
1797 struct rte_table_action *a = p->table[table_id].a;
1799 status = rte_table_action_meter_read(a,
1808 /* Allocate request */
1809 req = pipeline_msg_alloc();
1814 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1816 req->table_rule_mtr_read.data = data;
1817 req->table_rule_mtr_read.tc_mask = tc_mask;
1818 req->table_rule_mtr_read.clear = clear;
1820 /* Send request and wait for response */
1821 rsp = pipeline_msg_send_recv(p, req);
1826 status = rsp->status;
1828 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1831 pipeline_msg_free(rsp);
1837 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1838 const char *pipeline_name,
1841 struct rte_table_action_dscp_table *dscp_table)
1844 struct pipeline_msg_req *req;
1845 struct pipeline_msg_rsp *rsp;
1848 /* Check input params */
1849 if (pipeline_name == NULL ||
1853 p = softnic_pipeline_find(softnic, pipeline_name);
1855 table_id >= p->n_tables)
1858 if (!pipeline_is_running(p)) {
1859 struct rte_table_action *a = p->table[table_id].a;
1861 status = rte_table_action_dscp_table_update(a,
1868 /* Allocate request */
1869 req = pipeline_msg_alloc();
1874 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
1876 req->table_dscp_table_update.dscp_mask = dscp_mask;
1877 memcpy(&req->table_dscp_table_update.dscp_table,
1878 dscp_table, sizeof(*dscp_table));
1880 /* Send request and wait for response */
1881 rsp = pipeline_msg_send_recv(p, req);
1886 status = rsp->status;
1889 pipeline_msg_free(rsp);
1895 * Data plane threads: message handling
1897 static inline struct pipeline_msg_req *
1898 pipeline_msg_recv(struct rte_ring *msgq_req)
1900 struct pipeline_msg_req *req;
1902 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
1911 pipeline_msg_send(struct rte_ring *msgq_rsp,
1912 struct pipeline_msg_rsp *rsp)
1917 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
1918 } while (status == -ENOBUFS);
1921 static struct pipeline_msg_rsp *
1922 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
1923 struct pipeline_msg_req *req)
1925 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1926 uint32_t port_id = req->id;
1927 int clear = req->port_in_stats_read.clear;
1929 rsp->status = rte_pipeline_port_in_stats_read(p->p,
1931 &rsp->port_in_stats_read.stats,
1937 static struct pipeline_msg_rsp *
1938 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
1939 struct pipeline_msg_req *req)
1941 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1942 uint32_t port_id = req->id;
1944 rsp->status = rte_pipeline_port_in_enable(p->p,
1950 static struct pipeline_msg_rsp *
1951 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
1952 struct pipeline_msg_req *req)
1954 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1955 uint32_t port_id = req->id;
1957 rsp->status = rte_pipeline_port_in_disable(p->p,
1963 static struct pipeline_msg_rsp *
1964 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
1965 struct pipeline_msg_req *req)
1967 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1968 uint32_t port_id = req->id;
1969 int clear = req->port_out_stats_read.clear;
1971 rsp->status = rte_pipeline_port_out_stats_read(p->p,
1973 &rsp->port_out_stats_read.stats,
1979 static struct pipeline_msg_rsp *
1980 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
1981 struct pipeline_msg_req *req)
1983 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1984 uint32_t port_id = req->id;
1985 int clear = req->table_stats_read.clear;
1987 rsp->status = rte_pipeline_table_stats_read(p->p,
1989 &rsp->table_stats_read.stats,
1996 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2001 switch (depth / 32) {
2011 depth32[1] = depth - 32;
2019 depth32[2] = depth - 64;
2027 depth32[3] = depth - 96;
2043 match_convert(struct softnic_table_rule_match *mh,
2044 union table_rule_match_low_level *ml,
2047 memset(ml, 0, sizeof(*ml));
2049 switch (mh->match_type) {
2051 if (mh->match.acl.ip_version)
2053 ml->acl_add.field_value[0].value.u8 =
2054 mh->match.acl.proto;
2055 ml->acl_add.field_value[0].mask_range.u8 =
2056 mh->match.acl.proto_mask;
2058 ml->acl_add.field_value[1].value.u32 =
2059 mh->match.acl.ipv4.sa;
2060 ml->acl_add.field_value[1].mask_range.u32 =
2061 mh->match.acl.sa_depth;
2063 ml->acl_add.field_value[2].value.u32 =
2064 mh->match.acl.ipv4.da;
2065 ml->acl_add.field_value[2].mask_range.u32 =
2066 mh->match.acl.da_depth;
2068 ml->acl_add.field_value[3].value.u16 =
2070 ml->acl_add.field_value[3].mask_range.u16 =
2073 ml->acl_add.field_value[4].value.u16 =
2075 ml->acl_add.field_value[4].mask_range.u16 =
2078 ml->acl_add.priority =
2079 (int32_t)mh->match.acl.priority;
2081 ml->acl_delete.field_value[0].value.u8 =
2082 mh->match.acl.proto;
2083 ml->acl_delete.field_value[0].mask_range.u8 =
2084 mh->match.acl.proto_mask;
2086 ml->acl_delete.field_value[1].value.u32 =
2087 mh->match.acl.ipv4.sa;
2088 ml->acl_delete.field_value[1].mask_range.u32 =
2089 mh->match.acl.sa_depth;
2091 ml->acl_delete.field_value[2].value.u32 =
2092 mh->match.acl.ipv4.da;
2093 ml->acl_delete.field_value[2].mask_range.u32 =
2094 mh->match.acl.da_depth;
2096 ml->acl_delete.field_value[3].value.u16 =
2098 ml->acl_delete.field_value[3].mask_range.u16 =
2101 ml->acl_delete.field_value[4].value.u16 =
2103 ml->acl_delete.field_value[4].mask_range.u16 =
2109 (uint32_t *)mh->match.acl.ipv6.sa;
2111 (uint32_t *)mh->match.acl.ipv6.da;
2112 uint32_t sa32_depth[4], da32_depth[4];
2115 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2120 status = match_convert_ipv6_depth(
2121 mh->match.acl.da_depth,
2126 ml->acl_add.field_value[0].value.u8 =
2127 mh->match.acl.proto;
2128 ml->acl_add.field_value[0].mask_range.u8 =
2129 mh->match.acl.proto_mask;
2131 ml->acl_add.field_value[1].value.u32 = sa32[0];
2132 ml->acl_add.field_value[1].mask_range.u32 =
2134 ml->acl_add.field_value[2].value.u32 = sa32[1];
2135 ml->acl_add.field_value[2].mask_range.u32 =
2137 ml->acl_add.field_value[3].value.u32 = sa32[2];
2138 ml->acl_add.field_value[3].mask_range.u32 =
2140 ml->acl_add.field_value[4].value.u32 = sa32[3];
2141 ml->acl_add.field_value[4].mask_range.u32 =
2144 ml->acl_add.field_value[5].value.u32 = da32[0];
2145 ml->acl_add.field_value[5].mask_range.u32 =
2147 ml->acl_add.field_value[6].value.u32 = da32[1];
2148 ml->acl_add.field_value[6].mask_range.u32 =
2150 ml->acl_add.field_value[7].value.u32 = da32[2];
2151 ml->acl_add.field_value[7].mask_range.u32 =
2153 ml->acl_add.field_value[8].value.u32 = da32[3];
2154 ml->acl_add.field_value[8].mask_range.u32 =
2157 ml->acl_add.field_value[9].value.u16 =
2159 ml->acl_add.field_value[9].mask_range.u16 =
2162 ml->acl_add.field_value[10].value.u16 =
2164 ml->acl_add.field_value[10].mask_range.u16 =
2167 ml->acl_add.priority =
2168 (int32_t)mh->match.acl.priority;
2171 (uint32_t *)mh->match.acl.ipv6.sa;
2173 (uint32_t *)mh->match.acl.ipv6.da;
2174 uint32_t sa32_depth[4], da32_depth[4];
2177 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2182 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2187 ml->acl_delete.field_value[0].value.u8 =
2188 mh->match.acl.proto;
2189 ml->acl_delete.field_value[0].mask_range.u8 =
2190 mh->match.acl.proto_mask;
2192 ml->acl_delete.field_value[1].value.u32 =
2194 ml->acl_delete.field_value[1].mask_range.u32 =
2196 ml->acl_delete.field_value[2].value.u32 =
2198 ml->acl_delete.field_value[2].mask_range.u32 =
2200 ml->acl_delete.field_value[3].value.u32 =
2202 ml->acl_delete.field_value[3].mask_range.u32 =
2204 ml->acl_delete.field_value[4].value.u32 =
2206 ml->acl_delete.field_value[4].mask_range.u32 =
2209 ml->acl_delete.field_value[5].value.u32 =
2211 ml->acl_delete.field_value[5].mask_range.u32 =
2213 ml->acl_delete.field_value[6].value.u32 =
2215 ml->acl_delete.field_value[6].mask_range.u32 =
2217 ml->acl_delete.field_value[7].value.u32 =
2219 ml->acl_delete.field_value[7].mask_range.u32 =
2221 ml->acl_delete.field_value[8].value.u32 =
2223 ml->acl_delete.field_value[8].mask_range.u32 =
2226 ml->acl_delete.field_value[9].value.u16 =
2228 ml->acl_delete.field_value[9].mask_range.u16 =
2231 ml->acl_delete.field_value[10].value.u16 =
2233 ml->acl_delete.field_value[10].mask_range.u16 =
2239 ml->array.pos = mh->match.array.pos;
2243 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2247 if (mh->match.lpm.ip_version) {
2248 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2249 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2251 memcpy(ml->lpm_ipv6.ip,
2252 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2253 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2264 action_convert(struct rte_table_action *a,
2265 struct softnic_table_rule_action *action,
2266 struct rte_pipeline_table_entry *data)
2271 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2272 status = rte_table_action_apply(a,
2274 RTE_TABLE_ACTION_FWD,
2281 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2282 status = rte_table_action_apply(a,
2284 RTE_TABLE_ACTION_LB,
2291 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2292 status = rte_table_action_apply(a,
2294 RTE_TABLE_ACTION_MTR,
2301 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2302 status = rte_table_action_apply(a,
2304 RTE_TABLE_ACTION_TM,
2311 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2312 status = rte_table_action_apply(a,
2314 RTE_TABLE_ACTION_ENCAP,
2321 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2322 status = rte_table_action_apply(a,
2324 RTE_TABLE_ACTION_NAT,
2331 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2332 status = rte_table_action_apply(a,
2334 RTE_TABLE_ACTION_TTL,
2341 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2342 status = rte_table_action_apply(a,
2344 RTE_TABLE_ACTION_STATS,
2351 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2352 status = rte_table_action_apply(a,
2354 RTE_TABLE_ACTION_TIME,
2364 static struct pipeline_msg_rsp *
2365 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2366 struct pipeline_msg_req *req)
2368 union table_rule_match_low_level match_ll;
2369 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2370 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2371 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2372 struct rte_pipeline_table_entry *data_in, *data_out;
2373 uint32_t table_id = req->id;
2374 int key_found, status;
2375 struct rte_table_action *a = p->table_data[table_id].a;
2378 memset(p->buffer, 0, sizeof(p->buffer));
2379 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2381 status = match_convert(match, &match_ll, 1);
2387 status = action_convert(a, action, data_in);
2393 status = rte_pipeline_table_entry_add(p->p,
2404 /* Write response */
2406 rsp->table_rule_add.data = data_out;
2411 static struct pipeline_msg_rsp *
2412 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2413 struct pipeline_msg_req *req)
2415 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2416 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2417 struct rte_pipeline_table_entry *data_in, *data_out;
2418 uint32_t table_id = req->id;
2422 memset(p->buffer, 0, sizeof(p->buffer));
2423 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2425 data_in->action = action->fwd.action;
2426 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2427 data_in->port_id = action->fwd.id;
2428 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2429 data_in->table_id = action->fwd.id;
2431 /* Add default rule to table */
2432 status = rte_pipeline_table_default_entry_add(p->p,
2441 /* Write response */
2443 rsp->table_rule_add_default.data = data_out;
2448 static struct pipeline_msg_rsp *
2449 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2450 struct pipeline_msg_req *req)
2452 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2454 uint32_t table_id = req->id;
2455 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2456 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2457 struct rte_pipeline_table_entry **data =
2458 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2459 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2460 uint32_t bulk = req->table_rule_add_bulk.bulk;
2462 struct rte_table_action *a = p->table_data[table_id].a;
2463 union table_rule_match_low_level *match_ll;
2465 void **match_ll_ptr;
2466 struct rte_pipeline_table_entry **action_ll_ptr;
2470 /* Memory allocation */
2471 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2472 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2473 match_ll_ptr = calloc(n_rules, sizeof(void *));
2475 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2476 found = calloc(n_rules, sizeof(int));
2478 if (match_ll == NULL ||
2479 action_ll == NULL ||
2480 match_ll_ptr == NULL ||
2481 action_ll_ptr == NULL ||
2485 for (i = 0; i < n_rules; i++) {
2486 match_ll_ptr[i] = (void *)&match_ll[i];
2488 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2491 /* Rule match conversion */
2492 for (i = 0; i < n_rules; i++) {
2493 status = match_convert(&match[i], match_ll_ptr[i], 1);
2498 /* Rule action conversion */
2499 for (i = 0; i < n_rules; i++) {
2500 status = action_convert(a, &action[i], action_ll_ptr[i]);
2505 /* Add rule (match, action) to table */
2507 status = rte_pipeline_table_entry_add_bulk(p->p,
2517 for (i = 0; i < n_rules; i++) {
2518 status = rte_pipeline_table_entry_add(p->p,
2531 /* Write response */
2533 rsp->table_rule_add_bulk.n_rules = n_rules;
2537 free(action_ll_ptr);
2546 free(action_ll_ptr);
2552 rsp->table_rule_add_bulk.n_rules = 0;
2556 static struct pipeline_msg_rsp *
2557 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2558 struct pipeline_msg_req *req)
2560 union table_rule_match_low_level match_ll;
2561 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2562 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2563 uint32_t table_id = req->id;
2564 int key_found, status;
2566 status = match_convert(match, &match_ll, 0);
2572 rsp->status = rte_pipeline_table_entry_delete(p->p,
2581 static struct pipeline_msg_rsp *
2582 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2583 struct pipeline_msg_req *req)
2585 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2586 uint32_t table_id = req->id;
2588 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2595 static struct pipeline_msg_rsp *
2596 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2597 struct pipeline_msg_req *req)
2599 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2600 uint32_t table_id = req->id;
2601 void *data = req->table_rule_stats_read.data;
2602 int clear = req->table_rule_stats_read.clear;
2603 struct rte_table_action *a = p->table_data[table_id].a;
2605 rsp->status = rte_table_action_stats_read(a,
2607 &rsp->table_rule_stats_read.stats,
2613 static struct pipeline_msg_rsp *
2614 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2615 struct pipeline_msg_req *req)
2617 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2618 uint32_t table_id = req->id;
2619 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2620 struct rte_table_action_meter_profile *profile =
2621 &req->table_mtr_profile_add.profile;
2622 struct rte_table_action *a = p->table_data[table_id].a;
2624 rsp->status = rte_table_action_meter_profile_add(a,
2631 static struct pipeline_msg_rsp *
2632 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2633 struct pipeline_msg_req *req)
2635 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2636 uint32_t table_id = req->id;
2637 uint32_t meter_profile_id =
2638 req->table_mtr_profile_delete.meter_profile_id;
2639 struct rte_table_action *a = p->table_data[table_id].a;
2641 rsp->status = rte_table_action_meter_profile_delete(a,
2647 static struct pipeline_msg_rsp *
2648 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2649 struct pipeline_msg_req *req)
2651 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2652 uint32_t table_id = req->id;
2653 void *data = req->table_rule_mtr_read.data;
2654 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2655 int clear = req->table_rule_mtr_read.clear;
2656 struct rte_table_action *a = p->table_data[table_id].a;
2658 rsp->status = rte_table_action_meter_read(a,
2661 &rsp->table_rule_mtr_read.stats,
2667 static struct pipeline_msg_rsp *
2668 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2669 struct pipeline_msg_req *req)
2671 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2672 uint32_t table_id = req->id;
2673 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2674 struct rte_table_action_dscp_table *dscp_table =
2675 &req->table_dscp_table_update.dscp_table;
2676 struct rte_table_action *a = p->table_data[table_id].a;
2678 rsp->status = rte_table_action_dscp_table_update(a,
2686 pipeline_msg_handle(struct pipeline_data *p)
2689 struct pipeline_msg_req *req;
2690 struct pipeline_msg_rsp *rsp;
2692 req = pipeline_msg_recv(p->msgq_req);
2696 switch (req->type) {
2697 case PIPELINE_REQ_PORT_IN_STATS_READ:
2698 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2701 case PIPELINE_REQ_PORT_IN_ENABLE:
2702 rsp = pipeline_msg_handle_port_in_enable(p, req);
2705 case PIPELINE_REQ_PORT_IN_DISABLE:
2706 rsp = pipeline_msg_handle_port_in_disable(p, req);
2709 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2710 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2713 case PIPELINE_REQ_TABLE_STATS_READ:
2714 rsp = pipeline_msg_handle_table_stats_read(p, req);
2717 case PIPELINE_REQ_TABLE_RULE_ADD:
2718 rsp = pipeline_msg_handle_table_rule_add(p, req);
2721 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2722 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2725 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2726 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2729 case PIPELINE_REQ_TABLE_RULE_DELETE:
2730 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2733 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2734 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2737 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2738 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2741 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2742 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
2745 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
2746 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
2749 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
2750 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
2753 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
2754 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
2758 rsp = (struct pipeline_msg_rsp *)req;
2762 pipeline_msg_send(p->msgq_rsp, rsp);
2767 * Data plane threads: main
2770 rte_pmd_softnic_run(uint16_t port_id)
2772 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2773 struct pmd_internals *softnic;
2774 struct softnic_thread_data *t;
2775 uint32_t thread_id, j;
2777 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
2778 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
2781 softnic = dev->data->dev_private;
2782 thread_id = rte_lcore_id();
2783 t = &softnic->thread_data[thread_id];
2787 for (j = 0; j < t->n_pipelines; j++)
2788 rte_pipeline_run(t->p[j]);
2791 if ((t->iter & 0xFLLU) == 0) {
2792 uint64_t time = rte_get_tsc_cycles();
2793 uint64_t time_next_min = UINT64_MAX;
2795 if (time < t->time_next_min)
2798 /* Pipeline message queues */
2799 for (j = 0; j < t->n_pipelines; j++) {
2800 struct pipeline_data *p =
2801 &t->pipeline_data[j];
2802 uint64_t time_next = p->time_next;
2804 if (time_next <= time) {
2805 pipeline_msg_handle(p);
2806 rte_pipeline_flush(p->p);
2807 time_next = time + p->timer_period;
2808 p->time_next = time_next;
2811 if (time_next < time_next_min)
2812 time_next_min = time_next;
2815 /* Thread message queues */
2817 uint64_t time_next = t->time_next;
2819 if (time_next <= time) {
2820 thread_msg_handle(t);
2821 time_next = time + t->timer_period;
2822 t->time_next = time_next;
2825 if (time_next < time_next_min)
2826 time_next_min = time_next;
2829 t->time_next_min = time_next_min;