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;
1685 /* Check input params */
1686 if (pipeline_name == NULL ||
1690 p = softnic_pipeline_find(softnic, pipeline_name);
1692 table_id >= p->n_tables)
1695 if (!pipeline_is_running(p)) {
1696 struct rte_table_action *a = p->table[table_id].a;
1698 status = rte_table_action_meter_profile_add(a,
1705 /* Allocate request */
1706 req = pipeline_msg_alloc();
1711 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1713 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1714 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1716 /* Send request and wait for response */
1717 rsp = pipeline_msg_send_recv(p, req);
1722 status = rsp->status;
1725 pipeline_msg_free(rsp);
1731 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1732 const char *pipeline_name,
1734 uint32_t meter_profile_id)
1737 struct pipeline_msg_req *req;
1738 struct pipeline_msg_rsp *rsp;
1741 /* Check input params */
1742 if (pipeline_name == NULL)
1745 p = softnic_pipeline_find(softnic, pipeline_name);
1747 table_id >= p->n_tables)
1750 if (!pipeline_is_running(p)) {
1751 struct rte_table_action *a = p->table[table_id].a;
1753 status = rte_table_action_meter_profile_delete(a,
1759 /* Allocate request */
1760 req = pipeline_msg_alloc();
1765 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1767 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1769 /* Send request and wait for response */
1770 rsp = pipeline_msg_send_recv(p, req);
1775 status = rsp->status;
1778 pipeline_msg_free(rsp);
1784 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1785 const char *pipeline_name,
1789 struct rte_table_action_mtr_counters *stats,
1793 struct pipeline_msg_req *req;
1794 struct pipeline_msg_rsp *rsp;
1797 /* Check input params */
1798 if (pipeline_name == NULL ||
1803 p = softnic_pipeline_find(softnic, pipeline_name);
1805 table_id >= p->n_tables)
1808 if (!pipeline_is_running(p)) {
1809 struct rte_table_action *a = p->table[table_id].a;
1811 status = rte_table_action_meter_read(a,
1820 /* Allocate request */
1821 req = pipeline_msg_alloc();
1826 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1828 req->table_rule_mtr_read.data = data;
1829 req->table_rule_mtr_read.tc_mask = tc_mask;
1830 req->table_rule_mtr_read.clear = clear;
1832 /* Send request and wait for response */
1833 rsp = pipeline_msg_send_recv(p, req);
1838 status = rsp->status;
1840 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1843 pipeline_msg_free(rsp);
1849 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1850 const char *pipeline_name,
1853 struct rte_table_action_dscp_table *dscp_table)
1856 struct pipeline_msg_req *req;
1857 struct pipeline_msg_rsp *rsp;
1860 /* Check input params */
1861 if (pipeline_name == NULL ||
1865 p = softnic_pipeline_find(softnic, pipeline_name);
1867 table_id >= p->n_tables)
1870 if (!pipeline_is_running(p)) {
1871 struct rte_table_action *a = p->table[table_id].a;
1873 status = rte_table_action_dscp_table_update(a,
1880 /* Allocate request */
1881 req = pipeline_msg_alloc();
1886 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
1888 req->table_dscp_table_update.dscp_mask = dscp_mask;
1889 memcpy(&req->table_dscp_table_update.dscp_table,
1890 dscp_table, sizeof(*dscp_table));
1892 /* Send request and wait for response */
1893 rsp = pipeline_msg_send_recv(p, req);
1898 status = rsp->status;
1901 pipeline_msg_free(rsp);
1907 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
1908 const char *pipeline_name,
1911 struct rte_table_action_ttl_counters *stats,
1915 struct pipeline_msg_req *req;
1916 struct pipeline_msg_rsp *rsp;
1919 /* Check input params */
1920 if (pipeline_name == NULL ||
1925 p = softnic_pipeline_find(softnic, pipeline_name);
1927 table_id >= p->n_tables)
1930 if (!pipeline_is_running(p)) {
1931 struct rte_table_action *a = p->table[table_id].a;
1933 status = rte_table_action_ttl_read(a,
1941 /* Allocate request */
1942 req = pipeline_msg_alloc();
1947 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
1949 req->table_rule_ttl_read.data = data;
1950 req->table_rule_ttl_read.clear = clear;
1952 /* Send request and wait for response */
1953 rsp = pipeline_msg_send_recv(p, req);
1958 status = rsp->status;
1960 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
1963 pipeline_msg_free(rsp);
1969 * Data plane threads: message handling
1971 static inline struct pipeline_msg_req *
1972 pipeline_msg_recv(struct rte_ring *msgq_req)
1974 struct pipeline_msg_req *req;
1976 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
1985 pipeline_msg_send(struct rte_ring *msgq_rsp,
1986 struct pipeline_msg_rsp *rsp)
1991 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
1992 } while (status == -ENOBUFS);
1995 static struct pipeline_msg_rsp *
1996 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
1997 struct pipeline_msg_req *req)
1999 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2000 uint32_t port_id = req->id;
2001 int clear = req->port_in_stats_read.clear;
2003 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2005 &rsp->port_in_stats_read.stats,
2011 static struct pipeline_msg_rsp *
2012 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2013 struct pipeline_msg_req *req)
2015 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2016 uint32_t port_id = req->id;
2018 rsp->status = rte_pipeline_port_in_enable(p->p,
2024 static struct pipeline_msg_rsp *
2025 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2026 struct pipeline_msg_req *req)
2028 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2029 uint32_t port_id = req->id;
2031 rsp->status = rte_pipeline_port_in_disable(p->p,
2037 static struct pipeline_msg_rsp *
2038 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2039 struct pipeline_msg_req *req)
2041 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2042 uint32_t port_id = req->id;
2043 int clear = req->port_out_stats_read.clear;
2045 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2047 &rsp->port_out_stats_read.stats,
2053 static struct pipeline_msg_rsp *
2054 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2055 struct pipeline_msg_req *req)
2057 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2058 uint32_t port_id = req->id;
2059 int clear = req->table_stats_read.clear;
2061 rsp->status = rte_pipeline_table_stats_read(p->p,
2063 &rsp->table_stats_read.stats,
2070 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2075 switch (depth / 32) {
2085 depth32[1] = depth - 32;
2093 depth32[2] = depth - 64;
2101 depth32[3] = depth - 96;
2117 match_convert(struct softnic_table_rule_match *mh,
2118 union table_rule_match_low_level *ml,
2121 memset(ml, 0, sizeof(*ml));
2123 switch (mh->match_type) {
2125 if (mh->match.acl.ip_version)
2127 ml->acl_add.field_value[0].value.u8 =
2128 mh->match.acl.proto;
2129 ml->acl_add.field_value[0].mask_range.u8 =
2130 mh->match.acl.proto_mask;
2132 ml->acl_add.field_value[1].value.u32 =
2133 mh->match.acl.ipv4.sa;
2134 ml->acl_add.field_value[1].mask_range.u32 =
2135 mh->match.acl.sa_depth;
2137 ml->acl_add.field_value[2].value.u32 =
2138 mh->match.acl.ipv4.da;
2139 ml->acl_add.field_value[2].mask_range.u32 =
2140 mh->match.acl.da_depth;
2142 ml->acl_add.field_value[3].value.u16 =
2144 ml->acl_add.field_value[3].mask_range.u16 =
2147 ml->acl_add.field_value[4].value.u16 =
2149 ml->acl_add.field_value[4].mask_range.u16 =
2152 ml->acl_add.priority =
2153 (int32_t)mh->match.acl.priority;
2155 ml->acl_delete.field_value[0].value.u8 =
2156 mh->match.acl.proto;
2157 ml->acl_delete.field_value[0].mask_range.u8 =
2158 mh->match.acl.proto_mask;
2160 ml->acl_delete.field_value[1].value.u32 =
2161 mh->match.acl.ipv4.sa;
2162 ml->acl_delete.field_value[1].mask_range.u32 =
2163 mh->match.acl.sa_depth;
2165 ml->acl_delete.field_value[2].value.u32 =
2166 mh->match.acl.ipv4.da;
2167 ml->acl_delete.field_value[2].mask_range.u32 =
2168 mh->match.acl.da_depth;
2170 ml->acl_delete.field_value[3].value.u16 =
2172 ml->acl_delete.field_value[3].mask_range.u16 =
2175 ml->acl_delete.field_value[4].value.u16 =
2177 ml->acl_delete.field_value[4].mask_range.u16 =
2183 (uint32_t *)mh->match.acl.ipv6.sa;
2185 (uint32_t *)mh->match.acl.ipv6.da;
2186 uint32_t sa32_depth[4], da32_depth[4];
2189 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2194 status = match_convert_ipv6_depth(
2195 mh->match.acl.da_depth,
2200 ml->acl_add.field_value[0].value.u8 =
2201 mh->match.acl.proto;
2202 ml->acl_add.field_value[0].mask_range.u8 =
2203 mh->match.acl.proto_mask;
2205 ml->acl_add.field_value[1].value.u32 = sa32[0];
2206 ml->acl_add.field_value[1].mask_range.u32 =
2208 ml->acl_add.field_value[2].value.u32 = sa32[1];
2209 ml->acl_add.field_value[2].mask_range.u32 =
2211 ml->acl_add.field_value[3].value.u32 = sa32[2];
2212 ml->acl_add.field_value[3].mask_range.u32 =
2214 ml->acl_add.field_value[4].value.u32 = sa32[3];
2215 ml->acl_add.field_value[4].mask_range.u32 =
2218 ml->acl_add.field_value[5].value.u32 = da32[0];
2219 ml->acl_add.field_value[5].mask_range.u32 =
2221 ml->acl_add.field_value[6].value.u32 = da32[1];
2222 ml->acl_add.field_value[6].mask_range.u32 =
2224 ml->acl_add.field_value[7].value.u32 = da32[2];
2225 ml->acl_add.field_value[7].mask_range.u32 =
2227 ml->acl_add.field_value[8].value.u32 = da32[3];
2228 ml->acl_add.field_value[8].mask_range.u32 =
2231 ml->acl_add.field_value[9].value.u16 =
2233 ml->acl_add.field_value[9].mask_range.u16 =
2236 ml->acl_add.field_value[10].value.u16 =
2238 ml->acl_add.field_value[10].mask_range.u16 =
2241 ml->acl_add.priority =
2242 (int32_t)mh->match.acl.priority;
2245 (uint32_t *)mh->match.acl.ipv6.sa;
2247 (uint32_t *)mh->match.acl.ipv6.da;
2248 uint32_t sa32_depth[4], da32_depth[4];
2251 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2256 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2261 ml->acl_delete.field_value[0].value.u8 =
2262 mh->match.acl.proto;
2263 ml->acl_delete.field_value[0].mask_range.u8 =
2264 mh->match.acl.proto_mask;
2266 ml->acl_delete.field_value[1].value.u32 =
2268 ml->acl_delete.field_value[1].mask_range.u32 =
2270 ml->acl_delete.field_value[2].value.u32 =
2272 ml->acl_delete.field_value[2].mask_range.u32 =
2274 ml->acl_delete.field_value[3].value.u32 =
2276 ml->acl_delete.field_value[3].mask_range.u32 =
2278 ml->acl_delete.field_value[4].value.u32 =
2280 ml->acl_delete.field_value[4].mask_range.u32 =
2283 ml->acl_delete.field_value[5].value.u32 =
2285 ml->acl_delete.field_value[5].mask_range.u32 =
2287 ml->acl_delete.field_value[6].value.u32 =
2289 ml->acl_delete.field_value[6].mask_range.u32 =
2291 ml->acl_delete.field_value[7].value.u32 =
2293 ml->acl_delete.field_value[7].mask_range.u32 =
2295 ml->acl_delete.field_value[8].value.u32 =
2297 ml->acl_delete.field_value[8].mask_range.u32 =
2300 ml->acl_delete.field_value[9].value.u16 =
2302 ml->acl_delete.field_value[9].mask_range.u16 =
2305 ml->acl_delete.field_value[10].value.u16 =
2307 ml->acl_delete.field_value[10].mask_range.u16 =
2313 ml->array.pos = mh->match.array.pos;
2317 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2321 if (mh->match.lpm.ip_version) {
2322 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2323 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2325 memcpy(ml->lpm_ipv6.ip,
2326 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2327 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2338 action_convert(struct rte_table_action *a,
2339 struct softnic_table_rule_action *action,
2340 struct rte_pipeline_table_entry *data)
2345 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2346 status = rte_table_action_apply(a,
2348 RTE_TABLE_ACTION_FWD,
2355 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2356 status = rte_table_action_apply(a,
2358 RTE_TABLE_ACTION_LB,
2365 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2366 status = rte_table_action_apply(a,
2368 RTE_TABLE_ACTION_MTR,
2375 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2376 status = rte_table_action_apply(a,
2378 RTE_TABLE_ACTION_TM,
2385 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2386 status = rte_table_action_apply(a,
2388 RTE_TABLE_ACTION_ENCAP,
2395 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2396 status = rte_table_action_apply(a,
2398 RTE_TABLE_ACTION_NAT,
2405 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2406 status = rte_table_action_apply(a,
2408 RTE_TABLE_ACTION_TTL,
2415 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2416 status = rte_table_action_apply(a,
2418 RTE_TABLE_ACTION_STATS,
2425 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2426 status = rte_table_action_apply(a,
2428 RTE_TABLE_ACTION_TIME,
2438 static struct pipeline_msg_rsp *
2439 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2440 struct pipeline_msg_req *req)
2442 union table_rule_match_low_level match_ll;
2443 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2444 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2445 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2446 struct rte_pipeline_table_entry *data_in, *data_out;
2447 uint32_t table_id = req->id;
2448 int key_found, status;
2449 struct rte_table_action *a = p->table_data[table_id].a;
2452 memset(p->buffer, 0, sizeof(p->buffer));
2453 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2455 status = match_convert(match, &match_ll, 1);
2461 status = action_convert(a, action, data_in);
2467 status = rte_pipeline_table_entry_add(p->p,
2478 /* Write response */
2480 rsp->table_rule_add.data = data_out;
2485 static struct pipeline_msg_rsp *
2486 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2487 struct pipeline_msg_req *req)
2489 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2490 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2491 struct rte_pipeline_table_entry *data_in, *data_out;
2492 uint32_t table_id = req->id;
2496 memset(p->buffer, 0, sizeof(p->buffer));
2497 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2499 data_in->action = action->fwd.action;
2500 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2501 data_in->port_id = action->fwd.id;
2502 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2503 data_in->table_id = action->fwd.id;
2505 /* Add default rule to table */
2506 status = rte_pipeline_table_default_entry_add(p->p,
2515 /* Write response */
2517 rsp->table_rule_add_default.data = data_out;
2522 static struct pipeline_msg_rsp *
2523 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2524 struct pipeline_msg_req *req)
2526 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2528 uint32_t table_id = req->id;
2529 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2530 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2531 struct rte_pipeline_table_entry **data =
2532 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2533 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2534 uint32_t bulk = req->table_rule_add_bulk.bulk;
2536 struct rte_table_action *a = p->table_data[table_id].a;
2537 union table_rule_match_low_level *match_ll;
2539 void **match_ll_ptr;
2540 struct rte_pipeline_table_entry **action_ll_ptr;
2544 /* Memory allocation */
2545 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2546 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2547 match_ll_ptr = calloc(n_rules, sizeof(void *));
2549 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2550 found = calloc(n_rules, sizeof(int));
2552 if (match_ll == NULL ||
2553 action_ll == NULL ||
2554 match_ll_ptr == NULL ||
2555 action_ll_ptr == NULL ||
2559 for (i = 0; i < n_rules; i++) {
2560 match_ll_ptr[i] = (void *)&match_ll[i];
2562 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2565 /* Rule match conversion */
2566 for (i = 0; i < n_rules; i++) {
2567 status = match_convert(&match[i], match_ll_ptr[i], 1);
2572 /* Rule action conversion */
2573 for (i = 0; i < n_rules; i++) {
2574 status = action_convert(a, &action[i], action_ll_ptr[i]);
2579 /* Add rule (match, action) to table */
2581 status = rte_pipeline_table_entry_add_bulk(p->p,
2591 for (i = 0; i < n_rules; i++) {
2592 status = rte_pipeline_table_entry_add(p->p,
2605 /* Write response */
2607 rsp->table_rule_add_bulk.n_rules = n_rules;
2611 free(action_ll_ptr);
2620 free(action_ll_ptr);
2626 rsp->table_rule_add_bulk.n_rules = 0;
2630 static struct pipeline_msg_rsp *
2631 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2632 struct pipeline_msg_req *req)
2634 union table_rule_match_low_level match_ll;
2635 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2636 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2637 uint32_t table_id = req->id;
2638 int key_found, status;
2640 status = match_convert(match, &match_ll, 0);
2646 rsp->status = rte_pipeline_table_entry_delete(p->p,
2655 static struct pipeline_msg_rsp *
2656 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2657 struct pipeline_msg_req *req)
2659 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2660 uint32_t table_id = req->id;
2662 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2669 static struct pipeline_msg_rsp *
2670 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2671 struct pipeline_msg_req *req)
2673 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2674 uint32_t table_id = req->id;
2675 void *data = req->table_rule_stats_read.data;
2676 int clear = req->table_rule_stats_read.clear;
2677 struct rte_table_action *a = p->table_data[table_id].a;
2679 rsp->status = rte_table_action_stats_read(a,
2681 &rsp->table_rule_stats_read.stats,
2687 static struct pipeline_msg_rsp *
2688 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2689 struct pipeline_msg_req *req)
2691 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2692 uint32_t table_id = req->id;
2693 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2694 struct rte_table_action_meter_profile *profile =
2695 &req->table_mtr_profile_add.profile;
2696 struct rte_table_action *a = p->table_data[table_id].a;
2698 rsp->status = rte_table_action_meter_profile_add(a,
2705 static struct pipeline_msg_rsp *
2706 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2707 struct pipeline_msg_req *req)
2709 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2710 uint32_t table_id = req->id;
2711 uint32_t meter_profile_id =
2712 req->table_mtr_profile_delete.meter_profile_id;
2713 struct rte_table_action *a = p->table_data[table_id].a;
2715 rsp->status = rte_table_action_meter_profile_delete(a,
2721 static struct pipeline_msg_rsp *
2722 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2723 struct pipeline_msg_req *req)
2725 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2726 uint32_t table_id = req->id;
2727 void *data = req->table_rule_mtr_read.data;
2728 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2729 int clear = req->table_rule_mtr_read.clear;
2730 struct rte_table_action *a = p->table_data[table_id].a;
2732 rsp->status = rte_table_action_meter_read(a,
2735 &rsp->table_rule_mtr_read.stats,
2741 static struct pipeline_msg_rsp *
2742 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2743 struct pipeline_msg_req *req)
2745 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2746 uint32_t table_id = req->id;
2747 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2748 struct rte_table_action_dscp_table *dscp_table =
2749 &req->table_dscp_table_update.dscp_table;
2750 struct rte_table_action *a = p->table_data[table_id].a;
2752 rsp->status = rte_table_action_dscp_table_update(a,
2759 static struct pipeline_msg_rsp *
2760 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2761 struct pipeline_msg_req *req)
2763 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2764 uint32_t table_id = req->id;
2765 void *data = req->table_rule_ttl_read.data;
2766 int clear = req->table_rule_ttl_read.clear;
2767 struct rte_table_action *a = p->table_data[table_id].a;
2769 rsp->status = rte_table_action_ttl_read(a,
2771 &rsp->table_rule_ttl_read.stats,
2778 pipeline_msg_handle(struct pipeline_data *p)
2781 struct pipeline_msg_req *req;
2782 struct pipeline_msg_rsp *rsp;
2784 req = pipeline_msg_recv(p->msgq_req);
2788 switch (req->type) {
2789 case PIPELINE_REQ_PORT_IN_STATS_READ:
2790 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2793 case PIPELINE_REQ_PORT_IN_ENABLE:
2794 rsp = pipeline_msg_handle_port_in_enable(p, req);
2797 case PIPELINE_REQ_PORT_IN_DISABLE:
2798 rsp = pipeline_msg_handle_port_in_disable(p, req);
2801 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2802 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2805 case PIPELINE_REQ_TABLE_STATS_READ:
2806 rsp = pipeline_msg_handle_table_stats_read(p, req);
2809 case PIPELINE_REQ_TABLE_RULE_ADD:
2810 rsp = pipeline_msg_handle_table_rule_add(p, req);
2813 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2814 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2817 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2818 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2821 case PIPELINE_REQ_TABLE_RULE_DELETE:
2822 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2825 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2826 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2829 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2830 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2833 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2834 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
2837 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
2838 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
2841 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
2842 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
2845 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
2846 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
2849 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
2850 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
2854 rsp = (struct pipeline_msg_rsp *)req;
2858 pipeline_msg_send(p->msgq_rsp, rsp);
2863 * Data plane threads: main
2866 rte_pmd_softnic_run(uint16_t port_id)
2868 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2869 struct pmd_internals *softnic;
2870 struct softnic_thread_data *t;
2871 uint32_t thread_id, j;
2873 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
2874 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
2877 softnic = dev->data->dev_private;
2878 thread_id = rte_lcore_id();
2879 t = &softnic->thread_data[thread_id];
2883 for (j = 0; j < t->n_pipelines; j++)
2884 rte_pipeline_run(t->p[j]);
2887 if ((t->iter & 0xFLLU) == 0) {
2888 uint64_t time = rte_get_tsc_cycles();
2889 uint64_t time_next_min = UINT64_MAX;
2891 if (time < t->time_next_min)
2894 /* Pipeline message queues */
2895 for (j = 0; j < t->n_pipelines; j++) {
2896 struct pipeline_data *p =
2897 &t->pipeline_data[j];
2898 uint64_t time_next = p->time_next;
2900 if (time_next <= time) {
2901 pipeline_msg_handle(p);
2902 rte_pipeline_flush(p->p);
2903 time_next = time + p->timer_period;
2904 p->time_next = time_next;
2907 if (time_next < time_next_min)
2908 time_next_min = time_next;
2911 /* Thread message queues */
2913 uint64_t time_next = t->time_next;
2915 if (time_next <= time) {
2916 thread_msg_handle(t);
2917 time_next = time + t->timer_period;
2918 t->time_next = time_next;
2921 if (time_next < time_next_min)
2922 time_next_min = time_next;
2925 t->time_next_min = time_next_min;