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,
529 PIPELINE_REQ_TABLE_RULE_TTL_READ,
533 struct pipeline_msg_req_port_in_stats_read {
537 struct pipeline_msg_req_port_out_stats_read {
541 struct pipeline_msg_req_table_stats_read {
545 struct pipeline_msg_req_table_rule_add {
546 struct softnic_table_rule_match match;
547 struct softnic_table_rule_action action;
550 struct pipeline_msg_req_table_rule_add_default {
551 struct softnic_table_rule_action action;
554 struct pipeline_msg_req_table_rule_add_bulk {
555 struct softnic_table_rule_match *match;
556 struct softnic_table_rule_action *action;
562 struct pipeline_msg_req_table_rule_delete {
563 struct softnic_table_rule_match match;
566 struct pipeline_msg_req_table_rule_stats_read {
571 struct pipeline_msg_req_table_mtr_profile_add {
572 uint32_t meter_profile_id;
573 struct rte_table_action_meter_profile profile;
576 struct pipeline_msg_req_table_mtr_profile_delete {
577 uint32_t meter_profile_id;
580 struct pipeline_msg_req_table_rule_mtr_read {
586 struct pipeline_msg_req_table_dscp_table_update {
588 struct rte_table_action_dscp_table dscp_table;
591 struct pipeline_msg_req_table_rule_ttl_read {
596 struct pipeline_msg_req {
597 enum pipeline_req_type type;
598 uint32_t id; /* Port IN, port OUT or table ID */
602 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
603 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
604 struct pipeline_msg_req_table_stats_read table_stats_read;
605 struct pipeline_msg_req_table_rule_add table_rule_add;
606 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
607 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
608 struct pipeline_msg_req_table_rule_delete table_rule_delete;
609 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
610 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
611 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
612 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
613 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
614 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
618 struct pipeline_msg_rsp_port_in_stats_read {
619 struct rte_pipeline_port_in_stats stats;
622 struct pipeline_msg_rsp_port_out_stats_read {
623 struct rte_pipeline_port_out_stats stats;
626 struct pipeline_msg_rsp_table_stats_read {
627 struct rte_pipeline_table_stats stats;
630 struct pipeline_msg_rsp_table_rule_add {
634 struct pipeline_msg_rsp_table_rule_add_default {
638 struct pipeline_msg_rsp_table_rule_add_bulk {
642 struct pipeline_msg_rsp_table_rule_stats_read {
643 struct rte_table_action_stats_counters stats;
646 struct pipeline_msg_rsp_table_rule_mtr_read {
647 struct rte_table_action_mtr_counters stats;
650 struct pipeline_msg_rsp_table_rule_ttl_read {
651 struct rte_table_action_ttl_counters stats;
654 struct pipeline_msg_rsp {
659 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
660 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
661 struct pipeline_msg_rsp_table_stats_read table_stats_read;
662 struct pipeline_msg_rsp_table_rule_add table_rule_add;
663 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
664 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
665 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
666 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
667 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
674 static struct pipeline_msg_req *
675 pipeline_msg_alloc(void)
677 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
678 sizeof(struct pipeline_msg_rsp));
680 return calloc(1, size);
684 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
689 static struct pipeline_msg_rsp *
690 pipeline_msg_send_recv(struct pipeline *p,
691 struct pipeline_msg_req *req)
693 struct rte_ring *msgq_req = p->msgq_req;
694 struct rte_ring *msgq_rsp = p->msgq_rsp;
695 struct pipeline_msg_rsp *rsp;
700 status = rte_ring_sp_enqueue(msgq_req, req);
701 } while (status == -ENOBUFS);
705 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
706 } while (status != 0);
712 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
713 const char *pipeline_name,
715 struct rte_pipeline_port_in_stats *stats,
719 struct pipeline_msg_req *req;
720 struct pipeline_msg_rsp *rsp;
723 /* Check input params */
724 if (pipeline_name == NULL ||
728 p = softnic_pipeline_find(softnic, pipeline_name);
730 port_id >= p->n_ports_in)
733 if (!pipeline_is_running(p)) {
734 status = rte_pipeline_port_in_stats_read(p->p,
742 /* Allocate request */
743 req = pipeline_msg_alloc();
748 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
750 req->port_in_stats_read.clear = clear;
752 /* Send request and wait for response */
753 rsp = pipeline_msg_send_recv(p, req);
758 status = rsp->status;
760 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
763 pipeline_msg_free(rsp);
769 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
770 const char *pipeline_name,
774 struct pipeline_msg_req *req;
775 struct pipeline_msg_rsp *rsp;
778 /* Check input params */
779 if (pipeline_name == NULL)
782 p = softnic_pipeline_find(softnic, pipeline_name);
784 port_id >= p->n_ports_in)
787 if (!pipeline_is_running(p)) {
788 status = rte_pipeline_port_in_enable(p->p, port_id);
792 /* Allocate request */
793 req = pipeline_msg_alloc();
798 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
801 /* Send request and wait for response */
802 rsp = pipeline_msg_send_recv(p, req);
807 status = rsp->status;
810 pipeline_msg_free(rsp);
816 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
817 const char *pipeline_name,
821 struct pipeline_msg_req *req;
822 struct pipeline_msg_rsp *rsp;
825 /* Check input params */
826 if (pipeline_name == NULL)
829 p = softnic_pipeline_find(softnic, pipeline_name);
831 port_id >= p->n_ports_in)
834 if (!pipeline_is_running(p)) {
835 status = rte_pipeline_port_in_disable(p->p, port_id);
839 /* Allocate request */
840 req = pipeline_msg_alloc();
845 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
848 /* Send request and wait for response */
849 rsp = pipeline_msg_send_recv(p, req);
854 status = rsp->status;
857 pipeline_msg_free(rsp);
863 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
864 const char *pipeline_name,
866 struct rte_pipeline_port_out_stats *stats,
870 struct pipeline_msg_req *req;
871 struct pipeline_msg_rsp *rsp;
874 /* Check input params */
875 if (pipeline_name == NULL ||
879 p = softnic_pipeline_find(softnic, pipeline_name);
881 port_id >= p->n_ports_out)
884 if (!pipeline_is_running(p)) {
885 status = rte_pipeline_port_out_stats_read(p->p,
893 /* Allocate request */
894 req = pipeline_msg_alloc();
899 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
901 req->port_out_stats_read.clear = clear;
903 /* Send request and wait for response */
904 rsp = pipeline_msg_send_recv(p, req);
909 status = rsp->status;
911 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
914 pipeline_msg_free(rsp);
920 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
921 const char *pipeline_name,
923 struct rte_pipeline_table_stats *stats,
927 struct pipeline_msg_req *req;
928 struct pipeline_msg_rsp *rsp;
931 /* Check input params */
932 if (pipeline_name == NULL ||
936 p = softnic_pipeline_find(softnic, pipeline_name);
938 table_id >= p->n_tables)
941 if (!pipeline_is_running(p)) {
942 status = rte_pipeline_table_stats_read(p->p,
950 /* Allocate request */
951 req = pipeline_msg_alloc();
956 req->type = PIPELINE_REQ_TABLE_STATS_READ;
958 req->table_stats_read.clear = clear;
960 /* Send request and wait for response */
961 rsp = pipeline_msg_send_recv(p, req);
966 status = rsp->status;
968 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
971 pipeline_msg_free(rsp);
977 match_check(struct softnic_table_rule_match *match,
981 struct softnic_table *table;
985 table_id >= p->n_tables)
988 table = &p->table[table_id];
989 if (match->match_type != table->params.match_type)
992 switch (match->match_type) {
995 struct softnic_table_acl_params *t = &table->params.match.acl;
996 struct softnic_table_rule_match_acl *r = &match->match.acl;
998 if ((r->ip_version && (t->ip_version == 0)) ||
999 ((r->ip_version == 0) && t->ip_version))
1002 if (r->ip_version) {
1003 if (r->sa_depth > 32 ||
1007 if (r->sa_depth > 128 ||
1022 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1023 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1025 if ((r->ip_version && (t->key_size != 4)) ||
1026 ((r->ip_version == 0) && (t->key_size != 16)))
1029 if (r->ip_version) {
1048 action_check(struct softnic_table_rule_action *action,
1052 struct softnic_table_action_profile *ap;
1054 if (action == NULL ||
1056 table_id >= p->n_tables)
1059 ap = p->table[table_id].ap;
1060 if (action->action_mask != ap->params.action_mask)
1063 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1064 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1065 action->fwd.id >= p->n_ports_out)
1068 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1069 action->fwd.id >= p->n_tables)
1073 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1074 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1075 uint32_t tc_mask1 = action->mtr.tc_mask;
1077 if (tc_mask1 != tc_mask0)
1081 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1082 uint32_t n_subports_per_port =
1083 ap->params.tm.n_subports_per_port;
1084 uint32_t n_pipes_per_subport =
1085 ap->params.tm.n_pipes_per_subport;
1086 uint32_t subport_id = action->tm.subport_id;
1087 uint32_t pipe_id = action->tm.pipe_id;
1089 if (subport_id >= n_subports_per_port ||
1090 pipe_id >= n_pipes_per_subport)
1094 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1095 uint64_t encap_mask = ap->params.encap.encap_mask;
1096 enum rte_table_action_encap_type type = action->encap.type;
1098 if ((encap_mask & (1LLU << type)) == 0)
1102 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1103 int ip_version0 = ap->params.common.ip_version;
1104 int ip_version1 = action->nat.ip_version;
1106 if ((ip_version1 && (ip_version0 == 0)) ||
1107 ((ip_version1 == 0) && ip_version0))
1115 action_default_check(struct softnic_table_rule_action *action,
1119 if (action == NULL ||
1120 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1122 table_id >= p->n_tables)
1125 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1126 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1127 action->fwd.id >= p->n_ports_out)
1130 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1131 action->fwd.id >= p->n_tables)
1138 union table_rule_match_low_level {
1139 struct rte_table_acl_rule_add_params acl_add;
1140 struct rte_table_acl_rule_delete_params acl_delete;
1141 struct rte_table_array_key array;
1142 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1143 struct rte_table_lpm_key lpm_ipv4;
1144 struct rte_table_lpm_ipv6_key lpm_ipv6;
1148 match_convert(struct softnic_table_rule_match *mh,
1149 union table_rule_match_low_level *ml,
1153 action_convert(struct rte_table_action *a,
1154 struct softnic_table_rule_action *action,
1155 struct rte_pipeline_table_entry *data);
1158 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1159 const char *pipeline_name,
1161 struct softnic_table_rule_match *match,
1162 struct softnic_table_rule_action *action,
1166 struct pipeline_msg_req *req;
1167 struct pipeline_msg_rsp *rsp;
1170 /* Check input params */
1171 if (pipeline_name == NULL ||
1177 p = softnic_pipeline_find(softnic, pipeline_name);
1179 table_id >= p->n_tables ||
1180 match_check(match, p, table_id) ||
1181 action_check(action, p, table_id))
1184 if (!pipeline_is_running(p)) {
1185 struct rte_table_action *a = p->table[table_id].a;
1186 union table_rule_match_low_level match_ll;
1187 struct rte_pipeline_table_entry *data_in, *data_out;
1191 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1195 /* Table match-action rule conversion */
1196 data_in = (struct rte_pipeline_table_entry *)buffer;
1198 status = match_convert(match, &match_ll, 1);
1204 status = action_convert(a, action, data_in);
1210 /* Add rule (match, action) to table */
1211 status = rte_pipeline_table_entry_add(p->p,
1222 /* Write Response */
1229 /* Allocate request */
1230 req = pipeline_msg_alloc();
1235 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1237 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1238 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1240 /* Send request and wait for response */
1241 rsp = pipeline_msg_send_recv(p, req);
1246 status = rsp->status;
1248 *data = rsp->table_rule_add.data;
1251 pipeline_msg_free(rsp);
1257 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1258 const char *pipeline_name,
1260 struct softnic_table_rule_action *action,
1264 struct pipeline_msg_req *req;
1265 struct pipeline_msg_rsp *rsp;
1268 /* Check input params */
1269 if (pipeline_name == NULL ||
1274 p = softnic_pipeline_find(softnic, pipeline_name);
1276 table_id >= p->n_tables ||
1277 action_default_check(action, p, table_id))
1280 if (!pipeline_is_running(p)) {
1281 struct rte_pipeline_table_entry *data_in, *data_out;
1284 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1289 data_in = (struct rte_pipeline_table_entry *)buffer;
1291 data_in->action = action->fwd.action;
1292 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1293 data_in->port_id = action->fwd.id;
1294 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1295 data_in->table_id = action->fwd.id;
1297 /* Add default rule to table */
1298 status = rte_pipeline_table_default_entry_add(p->p,
1307 /* Write Response */
1314 /* Allocate request */
1315 req = pipeline_msg_alloc();
1320 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1322 memcpy(&req->table_rule_add_default.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_default.data;
1335 pipeline_msg_free(rsp);
1341 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1342 const char *pipeline_name,
1344 struct softnic_table_rule_match *match,
1345 struct softnic_table_rule_action *action,
1350 struct pipeline_msg_req *req;
1351 struct pipeline_msg_rsp *rsp;
1355 /* Check input params */
1356 if (pipeline_name == NULL ||
1364 p = softnic_pipeline_find(softnic, pipeline_name);
1366 table_id >= p->n_tables)
1369 for (i = 0; i < *n_rules; i++)
1370 if (match_check(match, p, table_id) ||
1371 action_check(action, p, table_id))
1374 if (!pipeline_is_running(p)) {
1375 struct rte_table_action *a = p->table[table_id].a;
1376 union table_rule_match_low_level *match_ll;
1378 void **match_ll_ptr;
1379 struct rte_pipeline_table_entry **action_ll_ptr;
1380 struct rte_pipeline_table_entry **entries_ptr =
1381 (struct rte_pipeline_table_entry **)data;
1383 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1386 /* Memory allocation */
1387 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1388 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1389 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1391 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1392 found = calloc(*n_rules, sizeof(int));
1394 if (match_ll == NULL ||
1395 action_ll == NULL ||
1396 match_ll_ptr == NULL ||
1397 action_ll_ptr == NULL ||
1401 for (i = 0; i < *n_rules; i++) {
1402 match_ll_ptr[i] = (void *)&match_ll[i];
1404 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1407 /* Rule match conversion */
1408 for (i = 0; i < *n_rules; i++) {
1409 status = match_convert(&match[i], match_ll_ptr[i], 1);
1414 /* Rule action conversion */
1415 for (i = 0; i < *n_rules; i++) {
1416 status = action_convert(a, &action[i], action_ll_ptr[i]);
1421 /* Add rule (match, action) to table */
1423 status = rte_pipeline_table_entry_add_bulk(p->p,
1433 for (i = 0; i < *n_rules; i++) {
1434 status = rte_pipeline_table_entry_add(p->p,
1449 free(action_ll_ptr);
1458 free(action_ll_ptr);
1467 /* Allocate request */
1468 req = pipeline_msg_alloc();
1473 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1475 req->table_rule_add_bulk.match = match;
1476 req->table_rule_add_bulk.action = action;
1477 req->table_rule_add_bulk.data = data;
1478 req->table_rule_add_bulk.n_rules = *n_rules;
1479 req->table_rule_add_bulk.bulk =
1480 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1482 /* Send request and wait for response */
1483 rsp = pipeline_msg_send_recv(p, req);
1488 status = rsp->status;
1490 *n_rules = rsp->table_rule_add_bulk.n_rules;
1493 pipeline_msg_free(rsp);
1499 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1500 const char *pipeline_name,
1502 struct softnic_table_rule_match *match)
1505 struct pipeline_msg_req *req;
1506 struct pipeline_msg_rsp *rsp;
1509 /* Check input params */
1510 if (pipeline_name == NULL ||
1514 p = softnic_pipeline_find(softnic, pipeline_name);
1516 table_id >= p->n_tables ||
1517 match_check(match, p, table_id))
1520 if (!pipeline_is_running(p)) {
1521 union table_rule_match_low_level match_ll;
1524 status = match_convert(match, &match_ll, 0);
1528 status = rte_pipeline_table_entry_delete(p->p,
1537 /* Allocate request */
1538 req = pipeline_msg_alloc();
1543 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1545 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1547 /* Send request and wait for response */
1548 rsp = pipeline_msg_send_recv(p, req);
1553 status = rsp->status;
1556 pipeline_msg_free(rsp);
1562 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1563 const char *pipeline_name,
1567 struct pipeline_msg_req *req;
1568 struct pipeline_msg_rsp *rsp;
1571 /* Check input params */
1572 if (pipeline_name == NULL)
1575 p = softnic_pipeline_find(softnic, pipeline_name);
1577 table_id >= p->n_tables)
1580 if (!pipeline_is_running(p)) {
1581 status = rte_pipeline_table_default_entry_delete(p->p,
1588 /* Allocate request */
1589 req = pipeline_msg_alloc();
1594 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1597 /* Send request and wait for response */
1598 rsp = pipeline_msg_send_recv(p, req);
1603 status = rsp->status;
1606 pipeline_msg_free(rsp);
1612 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1613 const char *pipeline_name,
1616 struct rte_table_action_stats_counters *stats,
1620 struct pipeline_msg_req *req;
1621 struct pipeline_msg_rsp *rsp;
1624 /* Check input params */
1625 if (pipeline_name == NULL ||
1630 p = softnic_pipeline_find(softnic, pipeline_name);
1632 table_id >= p->n_tables)
1635 if (!pipeline_is_running(p)) {
1636 struct rte_table_action *a = p->table[table_id].a;
1638 status = rte_table_action_stats_read(a,
1646 /* Allocate request */
1647 req = pipeline_msg_alloc();
1652 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1654 req->table_rule_stats_read.data = data;
1655 req->table_rule_stats_read.clear = clear;
1657 /* Send request and wait for response */
1658 rsp = pipeline_msg_send_recv(p, req);
1663 status = rsp->status;
1665 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1668 pipeline_msg_free(rsp);
1674 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1675 const char *pipeline_name,
1677 uint32_t meter_profile_id,
1678 struct rte_table_action_meter_profile *profile)
1681 struct pipeline_msg_req *req;
1682 struct pipeline_msg_rsp *rsp;
1683 struct softnic_table *table;
1684 struct softnic_table_meter_profile *mp;
1687 /* Check input params */
1688 if (pipeline_name == NULL ||
1692 p = softnic_pipeline_find(softnic, pipeline_name);
1694 table_id >= p->n_tables)
1697 table = &p->table[table_id];
1698 mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
1702 /* Resource Allocation */
1703 mp = calloc(1, sizeof(struct softnic_table_meter_profile));
1707 mp->meter_profile_id = meter_profile_id;
1708 memcpy(&mp->profile, profile, sizeof(mp->profile));
1710 if (!pipeline_is_running(p)) {
1711 status = rte_table_action_meter_profile_add(table->a,
1719 /* Add profile to the table. */
1720 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1725 /* Allocate request */
1726 req = pipeline_msg_alloc();
1733 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1735 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1736 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1738 /* Send request and wait for response */
1739 rsp = pipeline_msg_send_recv(p, req);
1746 status = rsp->status;
1748 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1753 pipeline_msg_free(rsp);
1759 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1760 const char *pipeline_name,
1762 uint32_t meter_profile_id)
1765 struct pipeline_msg_req *req;
1766 struct pipeline_msg_rsp *rsp;
1769 /* Check input params */
1770 if (pipeline_name == NULL)
1773 p = softnic_pipeline_find(softnic, pipeline_name);
1775 table_id >= p->n_tables)
1778 if (!pipeline_is_running(p)) {
1779 struct rte_table_action *a = p->table[table_id].a;
1781 status = rte_table_action_meter_profile_delete(a,
1787 /* Allocate request */
1788 req = pipeline_msg_alloc();
1793 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1795 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1797 /* Send request and wait for response */
1798 rsp = pipeline_msg_send_recv(p, req);
1803 status = rsp->status;
1806 pipeline_msg_free(rsp);
1812 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1813 const char *pipeline_name,
1817 struct rte_table_action_mtr_counters *stats,
1821 struct pipeline_msg_req *req;
1822 struct pipeline_msg_rsp *rsp;
1825 /* Check input params */
1826 if (pipeline_name == NULL ||
1831 p = softnic_pipeline_find(softnic, pipeline_name);
1833 table_id >= p->n_tables)
1836 if (!pipeline_is_running(p)) {
1837 struct rte_table_action *a = p->table[table_id].a;
1839 status = rte_table_action_meter_read(a,
1848 /* Allocate request */
1849 req = pipeline_msg_alloc();
1854 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1856 req->table_rule_mtr_read.data = data;
1857 req->table_rule_mtr_read.tc_mask = tc_mask;
1858 req->table_rule_mtr_read.clear = clear;
1860 /* Send request and wait for response */
1861 rsp = pipeline_msg_send_recv(p, req);
1866 status = rsp->status;
1868 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1871 pipeline_msg_free(rsp);
1877 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1878 const char *pipeline_name,
1881 struct rte_table_action_dscp_table *dscp_table)
1884 struct pipeline_msg_req *req;
1885 struct pipeline_msg_rsp *rsp;
1888 /* Check input params */
1889 if (pipeline_name == NULL ||
1893 p = softnic_pipeline_find(softnic, pipeline_name);
1895 table_id >= p->n_tables)
1898 if (!pipeline_is_running(p)) {
1899 struct rte_table_action *a = p->table[table_id].a;
1901 status = rte_table_action_dscp_table_update(a,
1905 /* Update table dscp table */
1907 memcpy(&p->table[table_id].dscp_table, dscp_table,
1908 sizeof(p->table[table_id].dscp_table));
1913 /* Allocate request */
1914 req = pipeline_msg_alloc();
1919 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
1921 req->table_dscp_table_update.dscp_mask = dscp_mask;
1922 memcpy(&req->table_dscp_table_update.dscp_table,
1923 dscp_table, sizeof(*dscp_table));
1925 /* Send request and wait for response */
1926 rsp = pipeline_msg_send_recv(p, req);
1931 status = rsp->status;
1933 /* Update table dscp table */
1935 memcpy(&p->table[table_id].dscp_table, dscp_table,
1936 sizeof(p->table[table_id].dscp_table));
1939 pipeline_msg_free(rsp);
1945 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
1946 const char *pipeline_name,
1949 struct rte_table_action_ttl_counters *stats,
1953 struct pipeline_msg_req *req;
1954 struct pipeline_msg_rsp *rsp;
1957 /* Check input params */
1958 if (pipeline_name == NULL ||
1963 p = softnic_pipeline_find(softnic, pipeline_name);
1965 table_id >= p->n_tables)
1968 if (!pipeline_is_running(p)) {
1969 struct rte_table_action *a = p->table[table_id].a;
1971 status = rte_table_action_ttl_read(a,
1979 /* Allocate request */
1980 req = pipeline_msg_alloc();
1985 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
1987 req->table_rule_ttl_read.data = data;
1988 req->table_rule_ttl_read.clear = clear;
1990 /* Send request and wait for response */
1991 rsp = pipeline_msg_send_recv(p, req);
1996 status = rsp->status;
1998 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2001 pipeline_msg_free(rsp);
2007 * Data plane threads: message handling
2009 static inline struct pipeline_msg_req *
2010 pipeline_msg_recv(struct rte_ring *msgq_req)
2012 struct pipeline_msg_req *req;
2014 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2023 pipeline_msg_send(struct rte_ring *msgq_rsp,
2024 struct pipeline_msg_rsp *rsp)
2029 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2030 } while (status == -ENOBUFS);
2033 static struct pipeline_msg_rsp *
2034 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2035 struct pipeline_msg_req *req)
2037 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2038 uint32_t port_id = req->id;
2039 int clear = req->port_in_stats_read.clear;
2041 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2043 &rsp->port_in_stats_read.stats,
2049 static struct pipeline_msg_rsp *
2050 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2051 struct pipeline_msg_req *req)
2053 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2054 uint32_t port_id = req->id;
2056 rsp->status = rte_pipeline_port_in_enable(p->p,
2062 static struct pipeline_msg_rsp *
2063 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2064 struct pipeline_msg_req *req)
2066 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2067 uint32_t port_id = req->id;
2069 rsp->status = rte_pipeline_port_in_disable(p->p,
2075 static struct pipeline_msg_rsp *
2076 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2077 struct pipeline_msg_req *req)
2079 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2080 uint32_t port_id = req->id;
2081 int clear = req->port_out_stats_read.clear;
2083 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2085 &rsp->port_out_stats_read.stats,
2091 static struct pipeline_msg_rsp *
2092 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2093 struct pipeline_msg_req *req)
2095 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2096 uint32_t port_id = req->id;
2097 int clear = req->table_stats_read.clear;
2099 rsp->status = rte_pipeline_table_stats_read(p->p,
2101 &rsp->table_stats_read.stats,
2108 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2113 switch (depth / 32) {
2123 depth32[1] = depth - 32;
2131 depth32[2] = depth - 64;
2139 depth32[3] = depth - 96;
2155 match_convert(struct softnic_table_rule_match *mh,
2156 union table_rule_match_low_level *ml,
2159 memset(ml, 0, sizeof(*ml));
2161 switch (mh->match_type) {
2163 if (mh->match.acl.ip_version)
2165 ml->acl_add.field_value[0].value.u8 =
2166 mh->match.acl.proto;
2167 ml->acl_add.field_value[0].mask_range.u8 =
2168 mh->match.acl.proto_mask;
2170 ml->acl_add.field_value[1].value.u32 =
2171 mh->match.acl.ipv4.sa;
2172 ml->acl_add.field_value[1].mask_range.u32 =
2173 mh->match.acl.sa_depth;
2175 ml->acl_add.field_value[2].value.u32 =
2176 mh->match.acl.ipv4.da;
2177 ml->acl_add.field_value[2].mask_range.u32 =
2178 mh->match.acl.da_depth;
2180 ml->acl_add.field_value[3].value.u16 =
2182 ml->acl_add.field_value[3].mask_range.u16 =
2185 ml->acl_add.field_value[4].value.u16 =
2187 ml->acl_add.field_value[4].mask_range.u16 =
2190 ml->acl_add.priority =
2191 (int32_t)mh->match.acl.priority;
2193 ml->acl_delete.field_value[0].value.u8 =
2194 mh->match.acl.proto;
2195 ml->acl_delete.field_value[0].mask_range.u8 =
2196 mh->match.acl.proto_mask;
2198 ml->acl_delete.field_value[1].value.u32 =
2199 mh->match.acl.ipv4.sa;
2200 ml->acl_delete.field_value[1].mask_range.u32 =
2201 mh->match.acl.sa_depth;
2203 ml->acl_delete.field_value[2].value.u32 =
2204 mh->match.acl.ipv4.da;
2205 ml->acl_delete.field_value[2].mask_range.u32 =
2206 mh->match.acl.da_depth;
2208 ml->acl_delete.field_value[3].value.u16 =
2210 ml->acl_delete.field_value[3].mask_range.u16 =
2213 ml->acl_delete.field_value[4].value.u16 =
2215 ml->acl_delete.field_value[4].mask_range.u16 =
2221 (uint32_t *)mh->match.acl.ipv6.sa;
2223 (uint32_t *)mh->match.acl.ipv6.da;
2224 uint32_t sa32_depth[4], da32_depth[4];
2227 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2232 status = match_convert_ipv6_depth(
2233 mh->match.acl.da_depth,
2238 ml->acl_add.field_value[0].value.u8 =
2239 mh->match.acl.proto;
2240 ml->acl_add.field_value[0].mask_range.u8 =
2241 mh->match.acl.proto_mask;
2243 ml->acl_add.field_value[1].value.u32 =
2244 rte_be_to_cpu_32(sa32[0]);
2245 ml->acl_add.field_value[1].mask_range.u32 =
2247 ml->acl_add.field_value[2].value.u32 =
2248 rte_be_to_cpu_32(sa32[1]);
2249 ml->acl_add.field_value[2].mask_range.u32 =
2251 ml->acl_add.field_value[3].value.u32 =
2252 rte_be_to_cpu_32(sa32[2]);
2253 ml->acl_add.field_value[3].mask_range.u32 =
2255 ml->acl_add.field_value[4].value.u32 =
2256 rte_be_to_cpu_32(sa32[3]);
2257 ml->acl_add.field_value[4].mask_range.u32 =
2260 ml->acl_add.field_value[5].value.u32 =
2261 rte_be_to_cpu_32(da32[0]);
2262 ml->acl_add.field_value[5].mask_range.u32 =
2264 ml->acl_add.field_value[6].value.u32 =
2265 rte_be_to_cpu_32(da32[1]);
2266 ml->acl_add.field_value[6].mask_range.u32 =
2268 ml->acl_add.field_value[7].value.u32 =
2269 rte_be_to_cpu_32(da32[2]);
2270 ml->acl_add.field_value[7].mask_range.u32 =
2272 ml->acl_add.field_value[8].value.u32 =
2273 rte_be_to_cpu_32(da32[3]);
2274 ml->acl_add.field_value[8].mask_range.u32 =
2277 ml->acl_add.field_value[9].value.u16 =
2279 ml->acl_add.field_value[9].mask_range.u16 =
2282 ml->acl_add.field_value[10].value.u16 =
2284 ml->acl_add.field_value[10].mask_range.u16 =
2287 ml->acl_add.priority =
2288 (int32_t)mh->match.acl.priority;
2291 (uint32_t *)mh->match.acl.ipv6.sa;
2293 (uint32_t *)mh->match.acl.ipv6.da;
2294 uint32_t sa32_depth[4], da32_depth[4];
2297 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2302 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2307 ml->acl_delete.field_value[0].value.u8 =
2308 mh->match.acl.proto;
2309 ml->acl_delete.field_value[0].mask_range.u8 =
2310 mh->match.acl.proto_mask;
2312 ml->acl_delete.field_value[1].value.u32 =
2313 rte_be_to_cpu_32(sa32[0]);
2314 ml->acl_delete.field_value[1].mask_range.u32 =
2316 ml->acl_delete.field_value[2].value.u32 =
2317 rte_be_to_cpu_32(sa32[1]);
2318 ml->acl_delete.field_value[2].mask_range.u32 =
2320 ml->acl_delete.field_value[3].value.u32 =
2321 rte_be_to_cpu_32(sa32[2]);
2322 ml->acl_delete.field_value[3].mask_range.u32 =
2324 ml->acl_delete.field_value[4].value.u32 =
2325 rte_be_to_cpu_32(sa32[3]);
2326 ml->acl_delete.field_value[4].mask_range.u32 =
2329 ml->acl_delete.field_value[5].value.u32 =
2330 rte_be_to_cpu_32(da32[0]);
2331 ml->acl_delete.field_value[5].mask_range.u32 =
2333 ml->acl_delete.field_value[6].value.u32 =
2334 rte_be_to_cpu_32(da32[1]);
2335 ml->acl_delete.field_value[6].mask_range.u32 =
2337 ml->acl_delete.field_value[7].value.u32 =
2338 rte_be_to_cpu_32(da32[2]);
2339 ml->acl_delete.field_value[7].mask_range.u32 =
2341 ml->acl_delete.field_value[8].value.u32 =
2342 rte_be_to_cpu_32(da32[3]);
2343 ml->acl_delete.field_value[8].mask_range.u32 =
2346 ml->acl_delete.field_value[9].value.u16 =
2348 ml->acl_delete.field_value[9].mask_range.u16 =
2351 ml->acl_delete.field_value[10].value.u16 =
2353 ml->acl_delete.field_value[10].mask_range.u16 =
2359 ml->array.pos = mh->match.array.pos;
2363 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2367 if (mh->match.lpm.ip_version) {
2368 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2369 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2371 memcpy(ml->lpm_ipv6.ip,
2372 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2373 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2384 action_convert(struct rte_table_action *a,
2385 struct softnic_table_rule_action *action,
2386 struct rte_pipeline_table_entry *data)
2391 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2392 status = rte_table_action_apply(a,
2394 RTE_TABLE_ACTION_FWD,
2401 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2402 status = rte_table_action_apply(a,
2404 RTE_TABLE_ACTION_LB,
2411 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2412 status = rte_table_action_apply(a,
2414 RTE_TABLE_ACTION_MTR,
2421 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2422 status = rte_table_action_apply(a,
2424 RTE_TABLE_ACTION_TM,
2431 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2432 status = rte_table_action_apply(a,
2434 RTE_TABLE_ACTION_ENCAP,
2441 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2442 status = rte_table_action_apply(a,
2444 RTE_TABLE_ACTION_NAT,
2451 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2452 status = rte_table_action_apply(a,
2454 RTE_TABLE_ACTION_TTL,
2461 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2462 status = rte_table_action_apply(a,
2464 RTE_TABLE_ACTION_STATS,
2471 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2472 status = rte_table_action_apply(a,
2474 RTE_TABLE_ACTION_TIME,
2481 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2482 status = rte_table_action_apply(a,
2484 RTE_TABLE_ACTION_TAG,
2491 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2492 status = rte_table_action_apply(a,
2494 RTE_TABLE_ACTION_DECAP,
2501 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2502 status = rte_table_action_apply(a,
2504 RTE_TABLE_ACTION_SYM_CRYPTO,
2505 &action->sym_crypto);
2514 static struct pipeline_msg_rsp *
2515 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2516 struct pipeline_msg_req *req)
2518 union table_rule_match_low_level match_ll;
2519 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2520 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2521 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2522 struct rte_pipeline_table_entry *data_in, *data_out;
2523 uint32_t table_id = req->id;
2524 int key_found, status;
2525 struct rte_table_action *a = p->table_data[table_id].a;
2528 memset(p->buffer, 0, sizeof(p->buffer));
2529 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2531 status = match_convert(match, &match_ll, 1);
2537 status = action_convert(a, action, data_in);
2543 status = rte_pipeline_table_entry_add(p->p,
2554 /* Write response */
2556 rsp->table_rule_add.data = data_out;
2561 static struct pipeline_msg_rsp *
2562 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2563 struct pipeline_msg_req *req)
2565 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2566 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2567 struct rte_pipeline_table_entry *data_in, *data_out;
2568 uint32_t table_id = req->id;
2572 memset(p->buffer, 0, sizeof(p->buffer));
2573 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2575 data_in->action = action->fwd.action;
2576 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2577 data_in->port_id = action->fwd.id;
2578 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2579 data_in->table_id = action->fwd.id;
2581 /* Add default rule to table */
2582 status = rte_pipeline_table_default_entry_add(p->p,
2591 /* Write response */
2593 rsp->table_rule_add_default.data = data_out;
2598 static struct pipeline_msg_rsp *
2599 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2600 struct pipeline_msg_req *req)
2602 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2604 uint32_t table_id = req->id;
2605 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2606 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2607 struct rte_pipeline_table_entry **data =
2608 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2609 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2610 uint32_t bulk = req->table_rule_add_bulk.bulk;
2612 struct rte_table_action *a = p->table_data[table_id].a;
2613 union table_rule_match_low_level *match_ll;
2615 void **match_ll_ptr;
2616 struct rte_pipeline_table_entry **action_ll_ptr;
2620 /* Memory allocation */
2621 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2622 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2623 match_ll_ptr = calloc(n_rules, sizeof(void *));
2625 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2626 found = calloc(n_rules, sizeof(int));
2628 if (match_ll == NULL ||
2629 action_ll == NULL ||
2630 match_ll_ptr == NULL ||
2631 action_ll_ptr == NULL ||
2635 for (i = 0; i < n_rules; i++) {
2636 match_ll_ptr[i] = (void *)&match_ll[i];
2638 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2641 /* Rule match conversion */
2642 for (i = 0; i < n_rules; i++) {
2643 status = match_convert(&match[i], match_ll_ptr[i], 1);
2648 /* Rule action conversion */
2649 for (i = 0; i < n_rules; i++) {
2650 status = action_convert(a, &action[i], action_ll_ptr[i]);
2655 /* Add rule (match, action) to table */
2657 status = rte_pipeline_table_entry_add_bulk(p->p,
2667 for (i = 0; i < n_rules; i++) {
2668 status = rte_pipeline_table_entry_add(p->p,
2681 /* Write response */
2683 rsp->table_rule_add_bulk.n_rules = n_rules;
2687 free(action_ll_ptr);
2696 free(action_ll_ptr);
2702 rsp->table_rule_add_bulk.n_rules = 0;
2706 static struct pipeline_msg_rsp *
2707 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2708 struct pipeline_msg_req *req)
2710 union table_rule_match_low_level match_ll;
2711 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2712 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2713 uint32_t table_id = req->id;
2714 int key_found, status;
2716 status = match_convert(match, &match_ll, 0);
2722 rsp->status = rte_pipeline_table_entry_delete(p->p,
2731 static struct pipeline_msg_rsp *
2732 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2733 struct pipeline_msg_req *req)
2735 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2736 uint32_t table_id = req->id;
2738 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2745 static struct pipeline_msg_rsp *
2746 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2747 struct pipeline_msg_req *req)
2749 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2750 uint32_t table_id = req->id;
2751 void *data = req->table_rule_stats_read.data;
2752 int clear = req->table_rule_stats_read.clear;
2753 struct rte_table_action *a = p->table_data[table_id].a;
2755 rsp->status = rte_table_action_stats_read(a,
2757 &rsp->table_rule_stats_read.stats,
2763 static struct pipeline_msg_rsp *
2764 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2765 struct pipeline_msg_req *req)
2767 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2768 uint32_t table_id = req->id;
2769 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2770 struct rte_table_action_meter_profile *profile =
2771 &req->table_mtr_profile_add.profile;
2772 struct rte_table_action *a = p->table_data[table_id].a;
2774 rsp->status = rte_table_action_meter_profile_add(a,
2781 static struct pipeline_msg_rsp *
2782 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2783 struct pipeline_msg_req *req)
2785 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2786 uint32_t table_id = req->id;
2787 uint32_t meter_profile_id =
2788 req->table_mtr_profile_delete.meter_profile_id;
2789 struct rte_table_action *a = p->table_data[table_id].a;
2791 rsp->status = rte_table_action_meter_profile_delete(a,
2797 static struct pipeline_msg_rsp *
2798 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2799 struct pipeline_msg_req *req)
2801 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2802 uint32_t table_id = req->id;
2803 void *data = req->table_rule_mtr_read.data;
2804 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2805 int clear = req->table_rule_mtr_read.clear;
2806 struct rte_table_action *a = p->table_data[table_id].a;
2808 rsp->status = rte_table_action_meter_read(a,
2811 &rsp->table_rule_mtr_read.stats,
2817 static struct pipeline_msg_rsp *
2818 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2819 struct pipeline_msg_req *req)
2821 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2822 uint32_t table_id = req->id;
2823 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2824 struct rte_table_action_dscp_table *dscp_table =
2825 &req->table_dscp_table_update.dscp_table;
2826 struct rte_table_action *a = p->table_data[table_id].a;
2828 rsp->status = rte_table_action_dscp_table_update(a,
2835 static struct pipeline_msg_rsp *
2836 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2837 struct pipeline_msg_req *req)
2839 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2840 uint32_t table_id = req->id;
2841 void *data = req->table_rule_ttl_read.data;
2842 int clear = req->table_rule_ttl_read.clear;
2843 struct rte_table_action *a = p->table_data[table_id].a;
2845 rsp->status = rte_table_action_ttl_read(a,
2847 &rsp->table_rule_ttl_read.stats,
2854 pipeline_msg_handle(struct pipeline_data *p)
2857 struct pipeline_msg_req *req;
2858 struct pipeline_msg_rsp *rsp;
2860 req = pipeline_msg_recv(p->msgq_req);
2864 switch (req->type) {
2865 case PIPELINE_REQ_PORT_IN_STATS_READ:
2866 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2869 case PIPELINE_REQ_PORT_IN_ENABLE:
2870 rsp = pipeline_msg_handle_port_in_enable(p, req);
2873 case PIPELINE_REQ_PORT_IN_DISABLE:
2874 rsp = pipeline_msg_handle_port_in_disable(p, req);
2877 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2878 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2881 case PIPELINE_REQ_TABLE_STATS_READ:
2882 rsp = pipeline_msg_handle_table_stats_read(p, req);
2885 case PIPELINE_REQ_TABLE_RULE_ADD:
2886 rsp = pipeline_msg_handle_table_rule_add(p, req);
2889 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2890 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2893 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2894 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2897 case PIPELINE_REQ_TABLE_RULE_DELETE:
2898 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2901 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2902 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2905 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2906 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2909 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2910 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
2913 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
2914 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
2917 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
2918 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
2921 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
2922 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
2925 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
2926 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
2930 rsp = (struct pipeline_msg_rsp *)req;
2934 pipeline_msg_send(p->msgq_rsp, rsp);
2939 * Data plane threads: main
2942 rte_pmd_softnic_run(uint16_t port_id)
2944 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2945 struct pmd_internals *softnic;
2946 struct softnic_thread_data *t;
2947 uint32_t thread_id, j;
2949 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
2950 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
2953 softnic = dev->data->dev_private;
2954 thread_id = rte_lcore_id();
2955 t = &softnic->thread_data[thread_id];
2959 for (j = 0; j < t->n_pipelines; j++)
2960 rte_pipeline_run(t->p[j]);
2963 if ((t->iter & 0xFLLU) == 0) {
2964 uint64_t time = rte_get_tsc_cycles();
2965 uint64_t time_next_min = UINT64_MAX;
2967 if (time < t->time_next_min)
2970 /* Pipeline message queues */
2971 for (j = 0; j < t->n_pipelines; j++) {
2972 struct pipeline_data *p =
2973 &t->pipeline_data[j];
2974 uint64_t time_next = p->time_next;
2976 if (time_next <= time) {
2977 pipeline_msg_handle(p);
2978 rte_pipeline_flush(p->p);
2979 time_next = time + p->timer_period;
2980 p->time_next = time_next;
2983 if (time_next < time_next_min)
2984 time_next_min = time_next;
2987 /* Thread message queues */
2989 uint64_t time_next = t->time_next;
2991 if (time_next <= time) {
2992 thread_msg_handle(t);
2993 time_next = time + t->timer_period;
2994 t->time_next = time_next;
2997 if (time_next < time_next_min)
2998 time_next_min = time_next;
3001 t->time_next_min = time_next_min;