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,
529 struct pipeline_msg_req_port_in_stats_read {
533 struct pipeline_msg_req_port_out_stats_read {
537 struct pipeline_msg_req_table_stats_read {
541 struct pipeline_msg_req_table_rule_add {
542 struct softnic_table_rule_match match;
543 struct softnic_table_rule_action action;
546 struct pipeline_msg_req_table_rule_add_default {
547 struct softnic_table_rule_action action;
550 struct pipeline_msg_req_table_rule_add_bulk {
551 struct softnic_table_rule_match *match;
552 struct softnic_table_rule_action *action;
558 struct pipeline_msg_req_table_rule_delete {
559 struct softnic_table_rule_match match;
562 struct pipeline_msg_req_table_rule_stats_read {
567 struct pipeline_msg_req {
568 enum pipeline_req_type type;
569 uint32_t id; /* Port IN, port OUT or table ID */
573 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
574 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
575 struct pipeline_msg_req_table_stats_read table_stats_read;
576 struct pipeline_msg_req_table_rule_add table_rule_add;
577 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
578 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
579 struct pipeline_msg_req_table_rule_delete table_rule_delete;
580 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
584 struct pipeline_msg_rsp_port_in_stats_read {
585 struct rte_pipeline_port_in_stats stats;
588 struct pipeline_msg_rsp_port_out_stats_read {
589 struct rte_pipeline_port_out_stats stats;
592 struct pipeline_msg_rsp_table_stats_read {
593 struct rte_pipeline_table_stats stats;
596 struct pipeline_msg_rsp_table_rule_add {
600 struct pipeline_msg_rsp_table_rule_add_default {
604 struct pipeline_msg_rsp_table_rule_add_bulk {
608 struct pipeline_msg_rsp_table_rule_stats_read {
609 struct rte_table_action_stats_counters stats;
612 struct pipeline_msg_rsp {
617 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
618 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
619 struct pipeline_msg_rsp_table_stats_read table_stats_read;
620 struct pipeline_msg_rsp_table_rule_add table_rule_add;
621 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
622 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
623 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
630 static struct pipeline_msg_req *
631 pipeline_msg_alloc(void)
633 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
634 sizeof(struct pipeline_msg_rsp));
636 return calloc(1, size);
640 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
645 static struct pipeline_msg_rsp *
646 pipeline_msg_send_recv(struct pipeline *p,
647 struct pipeline_msg_req *req)
649 struct rte_ring *msgq_req = p->msgq_req;
650 struct rte_ring *msgq_rsp = p->msgq_rsp;
651 struct pipeline_msg_rsp *rsp;
656 status = rte_ring_sp_enqueue(msgq_req, req);
657 } while (status == -ENOBUFS);
661 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
662 } while (status != 0);
668 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
669 const char *pipeline_name,
671 struct rte_pipeline_port_in_stats *stats,
675 struct pipeline_msg_req *req;
676 struct pipeline_msg_rsp *rsp;
679 /* Check input params */
680 if (pipeline_name == NULL ||
684 p = softnic_pipeline_find(softnic, pipeline_name);
686 port_id >= p->n_ports_in)
689 if (!pipeline_is_running(p)) {
690 status = rte_pipeline_port_in_stats_read(p->p,
698 /* Allocate request */
699 req = pipeline_msg_alloc();
704 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
706 req->port_in_stats_read.clear = clear;
708 /* Send request and wait for response */
709 rsp = pipeline_msg_send_recv(p, req);
714 status = rsp->status;
716 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
719 pipeline_msg_free(rsp);
725 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
726 const char *pipeline_name,
730 struct pipeline_msg_req *req;
731 struct pipeline_msg_rsp *rsp;
734 /* Check input params */
735 if (pipeline_name == NULL)
738 p = softnic_pipeline_find(softnic, pipeline_name);
740 port_id >= p->n_ports_in)
743 if (!pipeline_is_running(p)) {
744 status = rte_pipeline_port_in_enable(p->p, port_id);
748 /* Allocate request */
749 req = pipeline_msg_alloc();
754 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
757 /* Send request and wait for response */
758 rsp = pipeline_msg_send_recv(p, req);
763 status = rsp->status;
766 pipeline_msg_free(rsp);
772 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
773 const char *pipeline_name,
777 struct pipeline_msg_req *req;
778 struct pipeline_msg_rsp *rsp;
781 /* Check input params */
782 if (pipeline_name == NULL)
785 p = softnic_pipeline_find(softnic, pipeline_name);
787 port_id >= p->n_ports_in)
790 if (!pipeline_is_running(p)) {
791 status = rte_pipeline_port_in_disable(p->p, port_id);
795 /* Allocate request */
796 req = pipeline_msg_alloc();
801 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
804 /* Send request and wait for response */
805 rsp = pipeline_msg_send_recv(p, req);
810 status = rsp->status;
813 pipeline_msg_free(rsp);
819 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
820 const char *pipeline_name,
822 struct rte_pipeline_port_out_stats *stats,
826 struct pipeline_msg_req *req;
827 struct pipeline_msg_rsp *rsp;
830 /* Check input params */
831 if (pipeline_name == NULL ||
835 p = softnic_pipeline_find(softnic, pipeline_name);
837 port_id >= p->n_ports_out)
840 if (!pipeline_is_running(p)) {
841 status = rte_pipeline_port_out_stats_read(p->p,
849 /* Allocate request */
850 req = pipeline_msg_alloc();
855 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
857 req->port_out_stats_read.clear = clear;
859 /* Send request and wait for response */
860 rsp = pipeline_msg_send_recv(p, req);
865 status = rsp->status;
867 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
870 pipeline_msg_free(rsp);
876 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
877 const char *pipeline_name,
879 struct rte_pipeline_table_stats *stats,
883 struct pipeline_msg_req *req;
884 struct pipeline_msg_rsp *rsp;
887 /* Check input params */
888 if (pipeline_name == NULL ||
892 p = softnic_pipeline_find(softnic, pipeline_name);
894 table_id >= p->n_tables)
897 if (!pipeline_is_running(p)) {
898 status = rte_pipeline_table_stats_read(p->p,
906 /* Allocate request */
907 req = pipeline_msg_alloc();
912 req->type = PIPELINE_REQ_TABLE_STATS_READ;
914 req->table_stats_read.clear = clear;
916 /* Send request and wait for response */
917 rsp = pipeline_msg_send_recv(p, req);
922 status = rsp->status;
924 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
927 pipeline_msg_free(rsp);
933 match_check(struct softnic_table_rule_match *match,
937 struct softnic_table *table;
941 table_id >= p->n_tables)
944 table = &p->table[table_id];
945 if (match->match_type != table->params.match_type)
948 switch (match->match_type) {
951 struct softnic_table_acl_params *t = &table->params.match.acl;
952 struct softnic_table_rule_match_acl *r = &match->match.acl;
954 if ((r->ip_version && (t->ip_version == 0)) ||
955 ((r->ip_version == 0) && t->ip_version))
959 if (r->sa_depth > 32 ||
963 if (r->sa_depth > 128 ||
978 struct softnic_table_lpm_params *t = &table->params.match.lpm;
979 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
981 if ((r->ip_version && (t->key_size != 4)) ||
982 ((r->ip_version == 0) && (t->key_size != 16)))
1004 action_check(struct softnic_table_rule_action *action,
1008 struct softnic_table_action_profile *ap;
1010 if (action == NULL ||
1012 table_id >= p->n_tables)
1015 ap = p->table[table_id].ap;
1016 if (action->action_mask != ap->params.action_mask)
1019 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1020 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1021 action->fwd.id >= p->n_ports_out)
1024 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1025 action->fwd.id >= p->n_tables)
1029 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1030 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1031 uint32_t tc_mask1 = action->mtr.tc_mask;
1033 if (tc_mask1 != tc_mask0)
1037 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1038 uint32_t n_subports_per_port =
1039 ap->params.tm.n_subports_per_port;
1040 uint32_t n_pipes_per_subport =
1041 ap->params.tm.n_pipes_per_subport;
1042 uint32_t subport_id = action->tm.subport_id;
1043 uint32_t pipe_id = action->tm.pipe_id;
1045 if (subport_id >= n_subports_per_port ||
1046 pipe_id >= n_pipes_per_subport)
1050 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1051 uint64_t encap_mask = ap->params.encap.encap_mask;
1052 enum rte_table_action_encap_type type = action->encap.type;
1054 if ((encap_mask & (1LLU << type)) == 0)
1058 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1059 int ip_version0 = ap->params.common.ip_version;
1060 int ip_version1 = action->nat.ip_version;
1062 if ((ip_version1 && (ip_version0 == 0)) ||
1063 ((ip_version1 == 0) && ip_version0))
1071 action_default_check(struct softnic_table_rule_action *action,
1075 if (action == NULL ||
1076 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1078 table_id >= p->n_tables)
1081 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1082 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1083 action->fwd.id >= p->n_ports_out)
1086 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1087 action->fwd.id >= p->n_tables)
1094 union table_rule_match_low_level {
1095 struct rte_table_acl_rule_add_params acl_add;
1096 struct rte_table_acl_rule_delete_params acl_delete;
1097 struct rte_table_array_key array;
1098 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1099 struct rte_table_lpm_key lpm_ipv4;
1100 struct rte_table_lpm_ipv6_key lpm_ipv6;
1104 match_convert(struct softnic_table_rule_match *mh,
1105 union table_rule_match_low_level *ml,
1109 action_convert(struct rte_table_action *a,
1110 struct softnic_table_rule_action *action,
1111 struct rte_pipeline_table_entry *data);
1114 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1115 const char *pipeline_name,
1117 struct softnic_table_rule_match *match,
1118 struct softnic_table_rule_action *action,
1122 struct pipeline_msg_req *req;
1123 struct pipeline_msg_rsp *rsp;
1126 /* Check input params */
1127 if (pipeline_name == NULL ||
1133 p = softnic_pipeline_find(softnic, pipeline_name);
1135 table_id >= p->n_tables ||
1136 match_check(match, p, table_id) ||
1137 action_check(action, p, table_id))
1140 if (!pipeline_is_running(p)) {
1141 struct rte_table_action *a = p->table[table_id].a;
1142 union table_rule_match_low_level match_ll;
1143 struct rte_pipeline_table_entry *data_in, *data_out;
1147 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1151 /* Table match-action rule conversion */
1152 data_in = (struct rte_pipeline_table_entry *)buffer;
1154 status = match_convert(match, &match_ll, 1);
1160 status = action_convert(a, action, data_in);
1166 /* Add rule (match, action) to table */
1167 status = rte_pipeline_table_entry_add(p->p,
1178 /* Write Response */
1185 /* Allocate request */
1186 req = pipeline_msg_alloc();
1191 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1193 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1194 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1196 /* Send request and wait for response */
1197 rsp = pipeline_msg_send_recv(p, req);
1202 status = rsp->status;
1204 *data = rsp->table_rule_add.data;
1207 pipeline_msg_free(rsp);
1213 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1214 const char *pipeline_name,
1216 struct softnic_table_rule_action *action,
1220 struct pipeline_msg_req *req;
1221 struct pipeline_msg_rsp *rsp;
1224 /* Check input params */
1225 if (pipeline_name == NULL ||
1230 p = softnic_pipeline_find(softnic, pipeline_name);
1232 table_id >= p->n_tables ||
1233 action_default_check(action, p, table_id))
1236 if (!pipeline_is_running(p)) {
1237 struct rte_pipeline_table_entry *data_in, *data_out;
1240 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1245 data_in = (struct rte_pipeline_table_entry *)buffer;
1247 data_in->action = action->fwd.action;
1248 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1249 data_in->port_id = action->fwd.id;
1250 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1251 data_in->table_id = action->fwd.id;
1253 /* Add default rule to table */
1254 status = rte_pipeline_table_default_entry_add(p->p,
1263 /* Write Response */
1270 /* Allocate request */
1271 req = pipeline_msg_alloc();
1276 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1278 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1280 /* Send request and wait for response */
1281 rsp = pipeline_msg_send_recv(p, req);
1286 status = rsp->status;
1288 *data = rsp->table_rule_add_default.data;
1291 pipeline_msg_free(rsp);
1297 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1298 const char *pipeline_name,
1300 struct softnic_table_rule_match *match,
1301 struct softnic_table_rule_action *action,
1306 struct pipeline_msg_req *req;
1307 struct pipeline_msg_rsp *rsp;
1311 /* Check input params */
1312 if (pipeline_name == NULL ||
1320 p = softnic_pipeline_find(softnic, pipeline_name);
1322 table_id >= p->n_tables)
1325 for (i = 0; i < *n_rules; i++)
1326 if (match_check(match, p, table_id) ||
1327 action_check(action, p, table_id))
1330 if (!pipeline_is_running(p)) {
1331 struct rte_table_action *a = p->table[table_id].a;
1332 union table_rule_match_low_level *match_ll;
1334 void **match_ll_ptr;
1335 struct rte_pipeline_table_entry **action_ll_ptr;
1336 struct rte_pipeline_table_entry **entries_ptr =
1337 (struct rte_pipeline_table_entry **)data;
1339 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1342 /* Memory allocation */
1343 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1344 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1345 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1347 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1348 found = calloc(*n_rules, sizeof(int));
1350 if (match_ll == NULL ||
1351 action_ll == NULL ||
1352 match_ll_ptr == NULL ||
1353 action_ll_ptr == NULL ||
1357 for (i = 0; i < *n_rules; i++) {
1358 match_ll_ptr[i] = (void *)&match_ll[i];
1360 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1363 /* Rule match conversion */
1364 for (i = 0; i < *n_rules; i++) {
1365 status = match_convert(&match[i], match_ll_ptr[i], 1);
1370 /* Rule action conversion */
1371 for (i = 0; i < *n_rules; i++) {
1372 status = action_convert(a, &action[i], action_ll_ptr[i]);
1377 /* Add rule (match, action) to table */
1379 status = rte_pipeline_table_entry_add_bulk(p->p,
1389 for (i = 0; i < *n_rules; i++) {
1390 status = rte_pipeline_table_entry_add(p->p,
1405 free(action_ll_ptr);
1414 free(action_ll_ptr);
1423 /* Allocate request */
1424 req = pipeline_msg_alloc();
1429 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1431 req->table_rule_add_bulk.match = match;
1432 req->table_rule_add_bulk.action = action;
1433 req->table_rule_add_bulk.data = data;
1434 req->table_rule_add_bulk.n_rules = *n_rules;
1435 req->table_rule_add_bulk.bulk =
1436 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1438 /* Send request and wait for response */
1439 rsp = pipeline_msg_send_recv(p, req);
1444 status = rsp->status;
1446 *n_rules = rsp->table_rule_add_bulk.n_rules;
1449 pipeline_msg_free(rsp);
1455 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1456 const char *pipeline_name,
1458 struct softnic_table_rule_match *match)
1461 struct pipeline_msg_req *req;
1462 struct pipeline_msg_rsp *rsp;
1465 /* Check input params */
1466 if (pipeline_name == NULL ||
1470 p = softnic_pipeline_find(softnic, pipeline_name);
1472 table_id >= p->n_tables ||
1473 match_check(match, p, table_id))
1476 if (!pipeline_is_running(p)) {
1477 union table_rule_match_low_level match_ll;
1480 status = match_convert(match, &match_ll, 0);
1484 status = rte_pipeline_table_entry_delete(p->p,
1493 /* Allocate request */
1494 req = pipeline_msg_alloc();
1499 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1501 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1503 /* Send request and wait for response */
1504 rsp = pipeline_msg_send_recv(p, req);
1509 status = rsp->status;
1512 pipeline_msg_free(rsp);
1518 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1519 const char *pipeline_name,
1523 struct pipeline_msg_req *req;
1524 struct pipeline_msg_rsp *rsp;
1527 /* Check input params */
1528 if (pipeline_name == NULL)
1531 p = softnic_pipeline_find(softnic, pipeline_name);
1533 table_id >= p->n_tables)
1536 if (!pipeline_is_running(p)) {
1537 status = rte_pipeline_table_default_entry_delete(p->p,
1544 /* Allocate request */
1545 req = pipeline_msg_alloc();
1550 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1553 /* Send request and wait for response */
1554 rsp = pipeline_msg_send_recv(p, req);
1559 status = rsp->status;
1562 pipeline_msg_free(rsp);
1568 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1569 const char *pipeline_name,
1572 struct rte_table_action_stats_counters *stats,
1576 struct pipeline_msg_req *req;
1577 struct pipeline_msg_rsp *rsp;
1580 /* Check input params */
1581 if (pipeline_name == NULL ||
1586 p = softnic_pipeline_find(softnic, pipeline_name);
1588 table_id >= p->n_tables)
1591 if (!pipeline_is_running(p)) {
1592 struct rte_table_action *a = p->table[table_id].a;
1594 status = rte_table_action_stats_read(a,
1602 /* Allocate request */
1603 req = pipeline_msg_alloc();
1608 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1610 req->table_rule_stats_read.data = data;
1611 req->table_rule_stats_read.clear = clear;
1613 /* Send request and wait for response */
1614 rsp = pipeline_msg_send_recv(p, req);
1619 status = rsp->status;
1621 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1624 pipeline_msg_free(rsp);
1630 * Data plane threads: message handling
1632 static inline struct pipeline_msg_req *
1633 pipeline_msg_recv(struct rte_ring *msgq_req)
1635 struct pipeline_msg_req *req;
1637 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
1646 pipeline_msg_send(struct rte_ring *msgq_rsp,
1647 struct pipeline_msg_rsp *rsp)
1652 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
1653 } while (status == -ENOBUFS);
1656 static struct pipeline_msg_rsp *
1657 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
1658 struct pipeline_msg_req *req)
1660 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1661 uint32_t port_id = req->id;
1662 int clear = req->port_in_stats_read.clear;
1664 rsp->status = rte_pipeline_port_in_stats_read(p->p,
1666 &rsp->port_in_stats_read.stats,
1672 static struct pipeline_msg_rsp *
1673 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
1674 struct pipeline_msg_req *req)
1676 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1677 uint32_t port_id = req->id;
1679 rsp->status = rte_pipeline_port_in_enable(p->p,
1685 static struct pipeline_msg_rsp *
1686 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
1687 struct pipeline_msg_req *req)
1689 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1690 uint32_t port_id = req->id;
1692 rsp->status = rte_pipeline_port_in_disable(p->p,
1698 static struct pipeline_msg_rsp *
1699 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
1700 struct pipeline_msg_req *req)
1702 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1703 uint32_t port_id = req->id;
1704 int clear = req->port_out_stats_read.clear;
1706 rsp->status = rte_pipeline_port_out_stats_read(p->p,
1708 &rsp->port_out_stats_read.stats,
1714 static struct pipeline_msg_rsp *
1715 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
1716 struct pipeline_msg_req *req)
1718 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
1719 uint32_t port_id = req->id;
1720 int clear = req->table_stats_read.clear;
1722 rsp->status = rte_pipeline_table_stats_read(p->p,
1724 &rsp->table_stats_read.stats,
1731 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
1736 switch (depth / 32) {
1746 depth32[1] = depth - 32;
1754 depth32[2] = depth - 64;
1762 depth32[3] = depth - 96;
1778 match_convert(struct softnic_table_rule_match *mh,
1779 union table_rule_match_low_level *ml,
1782 memset(ml, 0, sizeof(*ml));
1784 switch (mh->match_type) {
1786 if (mh->match.acl.ip_version)
1788 ml->acl_add.field_value[0].value.u8 =
1789 mh->match.acl.proto;
1790 ml->acl_add.field_value[0].mask_range.u8 =
1791 mh->match.acl.proto_mask;
1793 ml->acl_add.field_value[1].value.u32 =
1794 mh->match.acl.ipv4.sa;
1795 ml->acl_add.field_value[1].mask_range.u32 =
1796 mh->match.acl.sa_depth;
1798 ml->acl_add.field_value[2].value.u32 =
1799 mh->match.acl.ipv4.da;
1800 ml->acl_add.field_value[2].mask_range.u32 =
1801 mh->match.acl.da_depth;
1803 ml->acl_add.field_value[3].value.u16 =
1805 ml->acl_add.field_value[3].mask_range.u16 =
1808 ml->acl_add.field_value[4].value.u16 =
1810 ml->acl_add.field_value[4].mask_range.u16 =
1813 ml->acl_add.priority =
1814 (int32_t)mh->match.acl.priority;
1816 ml->acl_delete.field_value[0].value.u8 =
1817 mh->match.acl.proto;
1818 ml->acl_delete.field_value[0].mask_range.u8 =
1819 mh->match.acl.proto_mask;
1821 ml->acl_delete.field_value[1].value.u32 =
1822 mh->match.acl.ipv4.sa;
1823 ml->acl_delete.field_value[1].mask_range.u32 =
1824 mh->match.acl.sa_depth;
1826 ml->acl_delete.field_value[2].value.u32 =
1827 mh->match.acl.ipv4.da;
1828 ml->acl_delete.field_value[2].mask_range.u32 =
1829 mh->match.acl.da_depth;
1831 ml->acl_delete.field_value[3].value.u16 =
1833 ml->acl_delete.field_value[3].mask_range.u16 =
1836 ml->acl_delete.field_value[4].value.u16 =
1838 ml->acl_delete.field_value[4].mask_range.u16 =
1844 (uint32_t *)mh->match.acl.ipv6.sa;
1846 (uint32_t *)mh->match.acl.ipv6.da;
1847 uint32_t sa32_depth[4], da32_depth[4];
1850 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
1855 status = match_convert_ipv6_depth(
1856 mh->match.acl.da_depth,
1861 ml->acl_add.field_value[0].value.u8 =
1862 mh->match.acl.proto;
1863 ml->acl_add.field_value[0].mask_range.u8 =
1864 mh->match.acl.proto_mask;
1866 ml->acl_add.field_value[1].value.u32 = sa32[0];
1867 ml->acl_add.field_value[1].mask_range.u32 =
1869 ml->acl_add.field_value[2].value.u32 = sa32[1];
1870 ml->acl_add.field_value[2].mask_range.u32 =
1872 ml->acl_add.field_value[3].value.u32 = sa32[2];
1873 ml->acl_add.field_value[3].mask_range.u32 =
1875 ml->acl_add.field_value[4].value.u32 = sa32[3];
1876 ml->acl_add.field_value[4].mask_range.u32 =
1879 ml->acl_add.field_value[5].value.u32 = da32[0];
1880 ml->acl_add.field_value[5].mask_range.u32 =
1882 ml->acl_add.field_value[6].value.u32 = da32[1];
1883 ml->acl_add.field_value[6].mask_range.u32 =
1885 ml->acl_add.field_value[7].value.u32 = da32[2];
1886 ml->acl_add.field_value[7].mask_range.u32 =
1888 ml->acl_add.field_value[8].value.u32 = da32[3];
1889 ml->acl_add.field_value[8].mask_range.u32 =
1892 ml->acl_add.field_value[9].value.u16 =
1894 ml->acl_add.field_value[9].mask_range.u16 =
1897 ml->acl_add.field_value[10].value.u16 =
1899 ml->acl_add.field_value[10].mask_range.u16 =
1902 ml->acl_add.priority =
1903 (int32_t)mh->match.acl.priority;
1906 (uint32_t *)mh->match.acl.ipv6.sa;
1908 (uint32_t *)mh->match.acl.ipv6.da;
1909 uint32_t sa32_depth[4], da32_depth[4];
1912 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
1917 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
1922 ml->acl_delete.field_value[0].value.u8 =
1923 mh->match.acl.proto;
1924 ml->acl_delete.field_value[0].mask_range.u8 =
1925 mh->match.acl.proto_mask;
1927 ml->acl_delete.field_value[1].value.u32 =
1929 ml->acl_delete.field_value[1].mask_range.u32 =
1931 ml->acl_delete.field_value[2].value.u32 =
1933 ml->acl_delete.field_value[2].mask_range.u32 =
1935 ml->acl_delete.field_value[3].value.u32 =
1937 ml->acl_delete.field_value[3].mask_range.u32 =
1939 ml->acl_delete.field_value[4].value.u32 =
1941 ml->acl_delete.field_value[4].mask_range.u32 =
1944 ml->acl_delete.field_value[5].value.u32 =
1946 ml->acl_delete.field_value[5].mask_range.u32 =
1948 ml->acl_delete.field_value[6].value.u32 =
1950 ml->acl_delete.field_value[6].mask_range.u32 =
1952 ml->acl_delete.field_value[7].value.u32 =
1954 ml->acl_delete.field_value[7].mask_range.u32 =
1956 ml->acl_delete.field_value[8].value.u32 =
1958 ml->acl_delete.field_value[8].mask_range.u32 =
1961 ml->acl_delete.field_value[9].value.u16 =
1963 ml->acl_delete.field_value[9].mask_range.u16 =
1966 ml->acl_delete.field_value[10].value.u16 =
1968 ml->acl_delete.field_value[10].mask_range.u16 =
1974 ml->array.pos = mh->match.array.pos;
1978 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
1982 if (mh->match.lpm.ip_version) {
1983 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
1984 ml->lpm_ipv4.depth = mh->match.lpm.depth;
1986 memcpy(ml->lpm_ipv6.ip,
1987 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
1988 ml->lpm_ipv6.depth = mh->match.lpm.depth;
1999 action_convert(struct rte_table_action *a,
2000 struct softnic_table_rule_action *action,
2001 struct rte_pipeline_table_entry *data)
2006 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2007 status = rte_table_action_apply(a,
2009 RTE_TABLE_ACTION_FWD,
2016 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2017 status = rte_table_action_apply(a,
2019 RTE_TABLE_ACTION_LB,
2026 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2027 status = rte_table_action_apply(a,
2029 RTE_TABLE_ACTION_MTR,
2036 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2037 status = rte_table_action_apply(a,
2039 RTE_TABLE_ACTION_TM,
2046 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2047 status = rte_table_action_apply(a,
2049 RTE_TABLE_ACTION_ENCAP,
2056 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2057 status = rte_table_action_apply(a,
2059 RTE_TABLE_ACTION_NAT,
2066 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2067 status = rte_table_action_apply(a,
2069 RTE_TABLE_ACTION_TTL,
2076 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2077 status = rte_table_action_apply(a,
2079 RTE_TABLE_ACTION_STATS,
2086 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2087 status = rte_table_action_apply(a,
2089 RTE_TABLE_ACTION_TIME,
2099 static struct pipeline_msg_rsp *
2100 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2101 struct pipeline_msg_req *req)
2103 union table_rule_match_low_level match_ll;
2104 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2105 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2106 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2107 struct rte_pipeline_table_entry *data_in, *data_out;
2108 uint32_t table_id = req->id;
2109 int key_found, status;
2110 struct rte_table_action *a = p->table_data[table_id].a;
2113 memset(p->buffer, 0, sizeof(p->buffer));
2114 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2116 status = match_convert(match, &match_ll, 1);
2122 status = action_convert(a, action, data_in);
2128 status = rte_pipeline_table_entry_add(p->p,
2139 /* Write response */
2141 rsp->table_rule_add.data = data_out;
2146 static struct pipeline_msg_rsp *
2147 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2148 struct pipeline_msg_req *req)
2150 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2151 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2152 struct rte_pipeline_table_entry *data_in, *data_out;
2153 uint32_t table_id = req->id;
2157 memset(p->buffer, 0, sizeof(p->buffer));
2158 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2160 data_in->action = action->fwd.action;
2161 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2162 data_in->port_id = action->fwd.id;
2163 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2164 data_in->table_id = action->fwd.id;
2166 /* Add default rule to table */
2167 status = rte_pipeline_table_default_entry_add(p->p,
2176 /* Write response */
2178 rsp->table_rule_add_default.data = data_out;
2183 static struct pipeline_msg_rsp *
2184 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2185 struct pipeline_msg_req *req)
2187 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2189 uint32_t table_id = req->id;
2190 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2191 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2192 struct rte_pipeline_table_entry **data =
2193 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2194 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2195 uint32_t bulk = req->table_rule_add_bulk.bulk;
2197 struct rte_table_action *a = p->table_data[table_id].a;
2198 union table_rule_match_low_level *match_ll;
2200 void **match_ll_ptr;
2201 struct rte_pipeline_table_entry **action_ll_ptr;
2205 /* Memory allocation */
2206 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2207 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2208 match_ll_ptr = calloc(n_rules, sizeof(void *));
2210 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2211 found = calloc(n_rules, sizeof(int));
2213 if (match_ll == NULL ||
2214 action_ll == NULL ||
2215 match_ll_ptr == NULL ||
2216 action_ll_ptr == NULL ||
2220 for (i = 0; i < n_rules; i++) {
2221 match_ll_ptr[i] = (void *)&match_ll[i];
2223 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2226 /* Rule match conversion */
2227 for (i = 0; i < n_rules; i++) {
2228 status = match_convert(&match[i], match_ll_ptr[i], 1);
2233 /* Rule action conversion */
2234 for (i = 0; i < n_rules; i++) {
2235 status = action_convert(a, &action[i], action_ll_ptr[i]);
2240 /* Add rule (match, action) to table */
2242 status = rte_pipeline_table_entry_add_bulk(p->p,
2252 for (i = 0; i < n_rules; i++) {
2253 status = rte_pipeline_table_entry_add(p->p,
2266 /* Write response */
2268 rsp->table_rule_add_bulk.n_rules = n_rules;
2272 free(action_ll_ptr);
2281 free(action_ll_ptr);
2287 rsp->table_rule_add_bulk.n_rules = 0;
2291 static struct pipeline_msg_rsp *
2292 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2293 struct pipeline_msg_req *req)
2295 union table_rule_match_low_level match_ll;
2296 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2297 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2298 uint32_t table_id = req->id;
2299 int key_found, status;
2301 status = match_convert(match, &match_ll, 0);
2307 rsp->status = rte_pipeline_table_entry_delete(p->p,
2316 static struct pipeline_msg_rsp *
2317 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2318 struct pipeline_msg_req *req)
2320 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2321 uint32_t table_id = req->id;
2323 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2330 static struct pipeline_msg_rsp *
2331 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2332 struct pipeline_msg_req *req)
2334 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2335 uint32_t table_id = req->id;
2336 void *data = req->table_rule_stats_read.data;
2337 int clear = req->table_rule_stats_read.clear;
2338 struct rte_table_action *a = p->table_data[table_id].a;
2340 rsp->status = rte_table_action_stats_read(a,
2342 &rsp->table_rule_stats_read.stats,
2349 pipeline_msg_handle(struct pipeline_data *p)
2352 struct pipeline_msg_req *req;
2353 struct pipeline_msg_rsp *rsp;
2355 req = pipeline_msg_recv(p->msgq_req);
2359 switch (req->type) {
2360 case PIPELINE_REQ_PORT_IN_STATS_READ:
2361 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2364 case PIPELINE_REQ_PORT_IN_ENABLE:
2365 rsp = pipeline_msg_handle_port_in_enable(p, req);
2368 case PIPELINE_REQ_PORT_IN_DISABLE:
2369 rsp = pipeline_msg_handle_port_in_disable(p, req);
2372 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2373 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2376 case PIPELINE_REQ_TABLE_STATS_READ:
2377 rsp = pipeline_msg_handle_table_stats_read(p, req);
2380 case PIPELINE_REQ_TABLE_RULE_ADD:
2381 rsp = pipeline_msg_handle_table_rule_add(p, req);
2384 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2385 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2388 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2389 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2392 case PIPELINE_REQ_TABLE_RULE_DELETE:
2393 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2396 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2397 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2400 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2401 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2405 rsp = (struct pipeline_msg_rsp *)req;
2409 pipeline_msg_send(p->msgq_rsp, rsp);
2414 * Data plane threads: main
2417 rte_pmd_softnic_run(uint16_t port_id)
2419 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
2420 struct pmd_internals *softnic;
2421 struct softnic_thread_data *t;
2422 uint32_t thread_id, j;
2424 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
2425 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
2428 softnic = dev->data->dev_private;
2429 thread_id = rte_lcore_id();
2430 t = &softnic->thread_data[thread_id];
2434 for (j = 0; j < t->n_pipelines; j++)
2435 rte_pipeline_run(t->p[j]);
2438 if ((t->iter & 0xFLLU) == 0) {
2439 uint64_t time = rte_get_tsc_cycles();
2440 uint64_t time_next_min = UINT64_MAX;
2442 if (time < t->time_next_min)
2445 /* Pipeline message queues */
2446 for (j = 0; j < t->n_pipelines; j++) {
2447 struct pipeline_data *p =
2448 &t->pipeline_data[j];
2449 uint64_t time_next = p->time_next;
2451 if (time_next <= time) {
2452 pipeline_msg_handle(p);
2453 rte_pipeline_flush(p->p);
2454 time_next = time + p->timer_period;
2455 p->time_next = time_next;
2458 if (time_next < time_next_min)
2459 time_next_min = time_next;
2462 /* Thread message queues */
2464 uint64_t time_next = t->time_next;
2466 if (time_next <= time) {
2467 thread_msg_handle(t);
2468 time_next = time + t->timer_period;
2469 t->time_next = time_next;
2472 if (time_next < time_next_min)
2473 time_next_min = time_next;
2476 t->time_next_min = time_next_min;