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,
1908 /* Allocate request */
1909 req = pipeline_msg_alloc();
1914 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
1916 req->table_dscp_table_update.dscp_mask = dscp_mask;
1917 memcpy(&req->table_dscp_table_update.dscp_table,
1918 dscp_table, sizeof(*dscp_table));
1920 /* Send request and wait for response */
1921 rsp = pipeline_msg_send_recv(p, req);
1926 status = rsp->status;
1929 pipeline_msg_free(rsp);
1935 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
1936 const char *pipeline_name,
1939 struct rte_table_action_ttl_counters *stats,
1943 struct pipeline_msg_req *req;
1944 struct pipeline_msg_rsp *rsp;
1947 /* Check input params */
1948 if (pipeline_name == NULL ||
1953 p = softnic_pipeline_find(softnic, pipeline_name);
1955 table_id >= p->n_tables)
1958 if (!pipeline_is_running(p)) {
1959 struct rte_table_action *a = p->table[table_id].a;
1961 status = rte_table_action_ttl_read(a,
1969 /* Allocate request */
1970 req = pipeline_msg_alloc();
1975 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
1977 req->table_rule_ttl_read.data = data;
1978 req->table_rule_ttl_read.clear = clear;
1980 /* Send request and wait for response */
1981 rsp = pipeline_msg_send_recv(p, req);
1986 status = rsp->status;
1988 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
1991 pipeline_msg_free(rsp);
1997 * Data plane threads: message handling
1999 static inline struct pipeline_msg_req *
2000 pipeline_msg_recv(struct rte_ring *msgq_req)
2002 struct pipeline_msg_req *req;
2004 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2013 pipeline_msg_send(struct rte_ring *msgq_rsp,
2014 struct pipeline_msg_rsp *rsp)
2019 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2020 } while (status == -ENOBUFS);
2023 static struct pipeline_msg_rsp *
2024 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2025 struct pipeline_msg_req *req)
2027 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2028 uint32_t port_id = req->id;
2029 int clear = req->port_in_stats_read.clear;
2031 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2033 &rsp->port_in_stats_read.stats,
2039 static struct pipeline_msg_rsp *
2040 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2041 struct pipeline_msg_req *req)
2043 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2044 uint32_t port_id = req->id;
2046 rsp->status = rte_pipeline_port_in_enable(p->p,
2052 static struct pipeline_msg_rsp *
2053 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2054 struct pipeline_msg_req *req)
2056 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2057 uint32_t port_id = req->id;
2059 rsp->status = rte_pipeline_port_in_disable(p->p,
2065 static struct pipeline_msg_rsp *
2066 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2067 struct pipeline_msg_req *req)
2069 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2070 uint32_t port_id = req->id;
2071 int clear = req->port_out_stats_read.clear;
2073 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2075 &rsp->port_out_stats_read.stats,
2081 static struct pipeline_msg_rsp *
2082 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2083 struct pipeline_msg_req *req)
2085 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2086 uint32_t port_id = req->id;
2087 int clear = req->table_stats_read.clear;
2089 rsp->status = rte_pipeline_table_stats_read(p->p,
2091 &rsp->table_stats_read.stats,
2098 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2103 switch (depth / 32) {
2113 depth32[1] = depth - 32;
2121 depth32[2] = depth - 64;
2129 depth32[3] = depth - 96;
2145 match_convert(struct softnic_table_rule_match *mh,
2146 union table_rule_match_low_level *ml,
2149 memset(ml, 0, sizeof(*ml));
2151 switch (mh->match_type) {
2153 if (mh->match.acl.ip_version)
2155 ml->acl_add.field_value[0].value.u8 =
2156 mh->match.acl.proto;
2157 ml->acl_add.field_value[0].mask_range.u8 =
2158 mh->match.acl.proto_mask;
2160 ml->acl_add.field_value[1].value.u32 =
2161 mh->match.acl.ipv4.sa;
2162 ml->acl_add.field_value[1].mask_range.u32 =
2163 mh->match.acl.sa_depth;
2165 ml->acl_add.field_value[2].value.u32 =
2166 mh->match.acl.ipv4.da;
2167 ml->acl_add.field_value[2].mask_range.u32 =
2168 mh->match.acl.da_depth;
2170 ml->acl_add.field_value[3].value.u16 =
2172 ml->acl_add.field_value[3].mask_range.u16 =
2175 ml->acl_add.field_value[4].value.u16 =
2177 ml->acl_add.field_value[4].mask_range.u16 =
2180 ml->acl_add.priority =
2181 (int32_t)mh->match.acl.priority;
2183 ml->acl_delete.field_value[0].value.u8 =
2184 mh->match.acl.proto;
2185 ml->acl_delete.field_value[0].mask_range.u8 =
2186 mh->match.acl.proto_mask;
2188 ml->acl_delete.field_value[1].value.u32 =
2189 mh->match.acl.ipv4.sa;
2190 ml->acl_delete.field_value[1].mask_range.u32 =
2191 mh->match.acl.sa_depth;
2193 ml->acl_delete.field_value[2].value.u32 =
2194 mh->match.acl.ipv4.da;
2195 ml->acl_delete.field_value[2].mask_range.u32 =
2196 mh->match.acl.da_depth;
2198 ml->acl_delete.field_value[3].value.u16 =
2200 ml->acl_delete.field_value[3].mask_range.u16 =
2203 ml->acl_delete.field_value[4].value.u16 =
2205 ml->acl_delete.field_value[4].mask_range.u16 =
2211 (uint32_t *)mh->match.acl.ipv6.sa;
2213 (uint32_t *)mh->match.acl.ipv6.da;
2214 uint32_t sa32_depth[4], da32_depth[4];
2217 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2222 status = match_convert_ipv6_depth(
2223 mh->match.acl.da_depth,
2228 ml->acl_add.field_value[0].value.u8 =
2229 mh->match.acl.proto;
2230 ml->acl_add.field_value[0].mask_range.u8 =
2231 mh->match.acl.proto_mask;
2233 ml->acl_add.field_value[1].value.u32 = sa32[0];
2234 ml->acl_add.field_value[1].mask_range.u32 =
2236 ml->acl_add.field_value[2].value.u32 = sa32[1];
2237 ml->acl_add.field_value[2].mask_range.u32 =
2239 ml->acl_add.field_value[3].value.u32 = sa32[2];
2240 ml->acl_add.field_value[3].mask_range.u32 =
2242 ml->acl_add.field_value[4].value.u32 = sa32[3];
2243 ml->acl_add.field_value[4].mask_range.u32 =
2246 ml->acl_add.field_value[5].value.u32 = da32[0];
2247 ml->acl_add.field_value[5].mask_range.u32 =
2249 ml->acl_add.field_value[6].value.u32 = da32[1];
2250 ml->acl_add.field_value[6].mask_range.u32 =
2252 ml->acl_add.field_value[7].value.u32 = da32[2];
2253 ml->acl_add.field_value[7].mask_range.u32 =
2255 ml->acl_add.field_value[8].value.u32 = da32[3];
2256 ml->acl_add.field_value[8].mask_range.u32 =
2259 ml->acl_add.field_value[9].value.u16 =
2261 ml->acl_add.field_value[9].mask_range.u16 =
2264 ml->acl_add.field_value[10].value.u16 =
2266 ml->acl_add.field_value[10].mask_range.u16 =
2269 ml->acl_add.priority =
2270 (int32_t)mh->match.acl.priority;
2273 (uint32_t *)mh->match.acl.ipv6.sa;
2275 (uint32_t *)mh->match.acl.ipv6.da;
2276 uint32_t sa32_depth[4], da32_depth[4];
2279 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2284 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2289 ml->acl_delete.field_value[0].value.u8 =
2290 mh->match.acl.proto;
2291 ml->acl_delete.field_value[0].mask_range.u8 =
2292 mh->match.acl.proto_mask;
2294 ml->acl_delete.field_value[1].value.u32 =
2296 ml->acl_delete.field_value[1].mask_range.u32 =
2298 ml->acl_delete.field_value[2].value.u32 =
2300 ml->acl_delete.field_value[2].mask_range.u32 =
2302 ml->acl_delete.field_value[3].value.u32 =
2304 ml->acl_delete.field_value[3].mask_range.u32 =
2306 ml->acl_delete.field_value[4].value.u32 =
2308 ml->acl_delete.field_value[4].mask_range.u32 =
2311 ml->acl_delete.field_value[5].value.u32 =
2313 ml->acl_delete.field_value[5].mask_range.u32 =
2315 ml->acl_delete.field_value[6].value.u32 =
2317 ml->acl_delete.field_value[6].mask_range.u32 =
2319 ml->acl_delete.field_value[7].value.u32 =
2321 ml->acl_delete.field_value[7].mask_range.u32 =
2323 ml->acl_delete.field_value[8].value.u32 =
2325 ml->acl_delete.field_value[8].mask_range.u32 =
2328 ml->acl_delete.field_value[9].value.u16 =
2330 ml->acl_delete.field_value[9].mask_range.u16 =
2333 ml->acl_delete.field_value[10].value.u16 =
2335 ml->acl_delete.field_value[10].mask_range.u16 =
2341 ml->array.pos = mh->match.array.pos;
2345 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2349 if (mh->match.lpm.ip_version) {
2350 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2351 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2353 memcpy(ml->lpm_ipv6.ip,
2354 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2355 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2366 action_convert(struct rte_table_action *a,
2367 struct softnic_table_rule_action *action,
2368 struct rte_pipeline_table_entry *data)
2373 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2374 status = rte_table_action_apply(a,
2376 RTE_TABLE_ACTION_FWD,
2383 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2384 status = rte_table_action_apply(a,
2386 RTE_TABLE_ACTION_LB,
2393 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2394 status = rte_table_action_apply(a,
2396 RTE_TABLE_ACTION_MTR,
2403 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2404 status = rte_table_action_apply(a,
2406 RTE_TABLE_ACTION_TM,
2413 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2414 status = rte_table_action_apply(a,
2416 RTE_TABLE_ACTION_ENCAP,
2423 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2424 status = rte_table_action_apply(a,
2426 RTE_TABLE_ACTION_NAT,
2433 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2434 status = rte_table_action_apply(a,
2436 RTE_TABLE_ACTION_TTL,
2443 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2444 status = rte_table_action_apply(a,
2446 RTE_TABLE_ACTION_STATS,
2453 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2454 status = rte_table_action_apply(a,
2456 RTE_TABLE_ACTION_TIME,
2466 static struct pipeline_msg_rsp *
2467 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2468 struct pipeline_msg_req *req)
2470 union table_rule_match_low_level match_ll;
2471 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2472 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2473 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2474 struct rte_pipeline_table_entry *data_in, *data_out;
2475 uint32_t table_id = req->id;
2476 int key_found, status;
2477 struct rte_table_action *a = p->table_data[table_id].a;
2480 memset(p->buffer, 0, sizeof(p->buffer));
2481 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2483 status = match_convert(match, &match_ll, 1);
2489 status = action_convert(a, action, data_in);
2495 status = rte_pipeline_table_entry_add(p->p,
2506 /* Write response */
2508 rsp->table_rule_add.data = data_out;
2513 static struct pipeline_msg_rsp *
2514 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2515 struct pipeline_msg_req *req)
2517 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2518 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2519 struct rte_pipeline_table_entry *data_in, *data_out;
2520 uint32_t table_id = req->id;
2524 memset(p->buffer, 0, sizeof(p->buffer));
2525 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2527 data_in->action = action->fwd.action;
2528 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2529 data_in->port_id = action->fwd.id;
2530 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2531 data_in->table_id = action->fwd.id;
2533 /* Add default rule to table */
2534 status = rte_pipeline_table_default_entry_add(p->p,
2543 /* Write response */
2545 rsp->table_rule_add_default.data = data_out;
2550 static struct pipeline_msg_rsp *
2551 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2552 struct pipeline_msg_req *req)
2554 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2556 uint32_t table_id = req->id;
2557 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2558 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2559 struct rte_pipeline_table_entry **data =
2560 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2561 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2562 uint32_t bulk = req->table_rule_add_bulk.bulk;
2564 struct rte_table_action *a = p->table_data[table_id].a;
2565 union table_rule_match_low_level *match_ll;
2567 void **match_ll_ptr;
2568 struct rte_pipeline_table_entry **action_ll_ptr;
2572 /* Memory allocation */
2573 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2574 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2575 match_ll_ptr = calloc(n_rules, sizeof(void *));
2577 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2578 found = calloc(n_rules, sizeof(int));
2580 if (match_ll == NULL ||
2581 action_ll == NULL ||
2582 match_ll_ptr == NULL ||
2583 action_ll_ptr == NULL ||
2587 for (i = 0; i < n_rules; i++) {
2588 match_ll_ptr[i] = (void *)&match_ll[i];
2590 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2593 /* Rule match conversion */
2594 for (i = 0; i < n_rules; i++) {
2595 status = match_convert(&match[i], match_ll_ptr[i], 1);
2600 /* Rule action conversion */
2601 for (i = 0; i < n_rules; i++) {
2602 status = action_convert(a, &action[i], action_ll_ptr[i]);
2607 /* Add rule (match, action) to table */
2609 status = rte_pipeline_table_entry_add_bulk(p->p,
2619 for (i = 0; i < n_rules; i++) {
2620 status = rte_pipeline_table_entry_add(p->p,
2633 /* Write response */
2635 rsp->table_rule_add_bulk.n_rules = n_rules;
2639 free(action_ll_ptr);
2648 free(action_ll_ptr);
2654 rsp->table_rule_add_bulk.n_rules = 0;
2658 static struct pipeline_msg_rsp *
2659 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2660 struct pipeline_msg_req *req)
2662 union table_rule_match_low_level match_ll;
2663 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2664 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2665 uint32_t table_id = req->id;
2666 int key_found, status;
2668 status = match_convert(match, &match_ll, 0);
2674 rsp->status = rte_pipeline_table_entry_delete(p->p,
2683 static struct pipeline_msg_rsp *
2684 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2685 struct pipeline_msg_req *req)
2687 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2688 uint32_t table_id = req->id;
2690 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2697 static struct pipeline_msg_rsp *
2698 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2699 struct pipeline_msg_req *req)
2701 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2702 uint32_t table_id = req->id;
2703 void *data = req->table_rule_stats_read.data;
2704 int clear = req->table_rule_stats_read.clear;
2705 struct rte_table_action *a = p->table_data[table_id].a;
2707 rsp->status = rte_table_action_stats_read(a,
2709 &rsp->table_rule_stats_read.stats,
2715 static struct pipeline_msg_rsp *
2716 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2717 struct pipeline_msg_req *req)
2719 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2720 uint32_t table_id = req->id;
2721 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2722 struct rte_table_action_meter_profile *profile =
2723 &req->table_mtr_profile_add.profile;
2724 struct rte_table_action *a = p->table_data[table_id].a;
2726 rsp->status = rte_table_action_meter_profile_add(a,
2733 static struct pipeline_msg_rsp *
2734 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2735 struct pipeline_msg_req *req)
2737 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2738 uint32_t table_id = req->id;
2739 uint32_t meter_profile_id =
2740 req->table_mtr_profile_delete.meter_profile_id;
2741 struct rte_table_action *a = p->table_data[table_id].a;
2743 rsp->status = rte_table_action_meter_profile_delete(a,
2749 static struct pipeline_msg_rsp *
2750 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2751 struct pipeline_msg_req *req)
2753 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2754 uint32_t table_id = req->id;
2755 void *data = req->table_rule_mtr_read.data;
2756 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2757 int clear = req->table_rule_mtr_read.clear;
2758 struct rte_table_action *a = p->table_data[table_id].a;
2760 rsp->status = rte_table_action_meter_read(a,
2763 &rsp->table_rule_mtr_read.stats,
2769 static struct pipeline_msg_rsp *
2770 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2771 struct pipeline_msg_req *req)
2773 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2774 uint32_t table_id = req->id;
2775 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2776 struct rte_table_action_dscp_table *dscp_table =
2777 &req->table_dscp_table_update.dscp_table;
2778 struct rte_table_action *a = p->table_data[table_id].a;
2780 rsp->status = rte_table_action_dscp_table_update(a,
2787 static struct pipeline_msg_rsp *
2788 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2789 struct pipeline_msg_req *req)
2791 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2792 uint32_t table_id = req->id;
2793 void *data = req->table_rule_ttl_read.data;
2794 int clear = req->table_rule_ttl_read.clear;
2795 struct rte_table_action *a = p->table_data[table_id].a;
2797 rsp->status = rte_table_action_ttl_read(a,
2799 &rsp->table_rule_ttl_read.stats,
2806 pipeline_msg_handle(struct pipeline_data *p)
2809 struct pipeline_msg_req *req;
2810 struct pipeline_msg_rsp *rsp;
2812 req = pipeline_msg_recv(p->msgq_req);
2816 switch (req->type) {
2817 case PIPELINE_REQ_PORT_IN_STATS_READ:
2818 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2821 case PIPELINE_REQ_PORT_IN_ENABLE:
2822 rsp = pipeline_msg_handle_port_in_enable(p, req);
2825 case PIPELINE_REQ_PORT_IN_DISABLE:
2826 rsp = pipeline_msg_handle_port_in_disable(p, req);
2829 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2830 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2833 case PIPELINE_REQ_TABLE_STATS_READ:
2834 rsp = pipeline_msg_handle_table_stats_read(p, req);
2837 case PIPELINE_REQ_TABLE_RULE_ADD:
2838 rsp = pipeline_msg_handle_table_rule_add(p, req);
2841 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2842 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2845 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2846 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2849 case PIPELINE_REQ_TABLE_RULE_DELETE:
2850 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2853 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2854 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2857 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2858 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2861 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2862 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
2865 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
2866 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
2869 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
2870 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
2873 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
2874 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
2877 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
2878 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
2882 rsp = (struct pipeline_msg_rsp *)req;
2886 pipeline_msg_send(p->msgq_rsp, rsp);
2891 * Data plane threads: main
2894 rte_pmd_softnic_run(uint16_t port_id)
2896 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2897 struct pmd_internals *softnic;
2898 struct softnic_thread_data *t;
2899 uint32_t thread_id, j;
2901 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
2902 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
2905 softnic = dev->data->dev_private;
2906 thread_id = rte_lcore_id();
2907 t = &softnic->thread_data[thread_id];
2911 for (j = 0; j < t->n_pipelines; j++)
2912 rte_pipeline_run(t->p[j]);
2915 if ((t->iter & 0xFLLU) == 0) {
2916 uint64_t time = rte_get_tsc_cycles();
2917 uint64_t time_next_min = UINT64_MAX;
2919 if (time < t->time_next_min)
2922 /* Pipeline message queues */
2923 for (j = 0; j < t->n_pipelines; j++) {
2924 struct pipeline_data *p =
2925 &t->pipeline_data[j];
2926 uint64_t time_next = p->time_next;
2928 if (time_next <= time) {
2929 pipeline_msg_handle(p);
2930 rte_pipeline_flush(p->p);
2931 time_next = time + p->timer_period;
2932 p->time_next = time_next;
2935 if (time_next < time_next_min)
2936 time_next_min = time_next;
2939 /* Thread message queues */
2941 uint64_t time_next = t->time_next;
2943 if (time_next <= time) {
2944 thread_msg_handle(t);
2945 time_next = time + t->timer_period;
2946 t->time_next = time_next;
2949 if (time_next < time_next_min)
2950 time_next_min = time_next;
2953 t->time_next_min = time_next_min;