1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
7 #include <rte_common.h>
8 #include <rte_cycles.h>
10 #include <rte_service_component.h>
13 #include <rte_table_acl.h>
14 #include <rte_table_array.h>
15 #include <rte_table_hash.h>
16 #include <rte_table_lpm.h>
17 #include <rte_table_lpm_ipv6.h>
18 #include "rte_eth_softnic_internals.h"
21 * Main thread: data plane thread init
24 softnic_thread_free(struct pmd_internals *softnic)
28 RTE_LCORE_FOREACH_WORKER(i) {
29 struct softnic_thread *t = &softnic->thread[i];
33 rte_ring_free(t->msgq_req);
36 rte_ring_free(t->msgq_rsp);
41 softnic_thread_init(struct pmd_internals *softnic)
45 for (i = 0; i < RTE_MAX_LCORE; i++) {
46 char ring_name[NAME_MAX];
47 struct rte_ring *msgq_req, *msgq_rsp;
48 struct softnic_thread *t = &softnic->thread[i];
49 struct softnic_thread_data *t_data = &softnic->thread_data[i];
50 uint32_t cpu_id = rte_lcore_to_socket_id(i);
53 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ",
57 msgq_req = rte_ring_create(ring_name,
60 RING_F_SP_ENQ | RING_F_SC_DEQ);
62 if (msgq_req == NULL) {
63 softnic_thread_free(softnic);
67 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP",
71 msgq_rsp = rte_ring_create(ring_name,
74 RING_F_SP_ENQ | RING_F_SC_DEQ);
76 if (msgq_rsp == NULL) {
77 softnic_thread_free(softnic);
81 /* Main thread records */
82 t->msgq_req = msgq_req;
83 t->msgq_rsp = msgq_rsp;
84 t->service_id = UINT32_MAX;
86 /* Data plane thread records */
87 t_data->n_pipelines = 0;
88 t_data->msgq_req = msgq_req;
89 t_data->msgq_rsp = msgq_rsp;
90 t_data->timer_period =
91 (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
92 t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
93 t_data->time_next_min = t_data->time_next;
100 thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id)
102 if (thread_id == rte_get_main_lcore())
103 return 0; /* FALSE */
105 if (softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_SERVICE))
107 if (!softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_RTE))
110 return 0; /* FALSE */
114 thread_is_running(uint32_t thread_id)
116 enum rte_lcore_state_t thread_state;
118 thread_state = rte_eal_get_lcore_state(thread_id);
119 return (thread_state == RUNNING)? 1 : 0;
123 rte_pmd_softnic_run_internal(void *arg);
126 thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
128 struct rte_service_spec service_params;
129 struct softnic_thread *t = &softnic->thread[thread_id];
130 struct rte_eth_dev *dev;
135 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
139 dev = &rte_eth_devices[port_id];
140 snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
141 softnic->params.name,
143 service_params.callback = rte_pmd_softnic_run_internal;
144 service_params.callback_userdata = dev;
145 service_params.capabilities = 0;
146 service_params.socket_id = (int)softnic->params.cpu_id;
148 /* service register */
149 status = rte_service_component_register(&service_params, &t->service_id);
153 status = rte_service_component_runstate_set(t->service_id, 1);
155 rte_service_component_unregister(t->service_id);
156 t->service_id = UINT32_MAX;
160 status = rte_service_runstate_set(t->service_id, 1);
162 rte_service_component_runstate_set(t->service_id, 0);
163 rte_service_component_unregister(t->service_id);
164 t->service_id = UINT32_MAX;
168 /* service map to thread */
169 status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
171 rte_service_runstate_set(t->service_id, 0);
172 rte_service_component_runstate_set(t->service_id, 0);
173 rte_service_component_unregister(t->service_id);
174 t->service_id = UINT32_MAX;
182 thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
184 struct softnic_thread *t = &softnic->thread[thread_id];
186 /* service unmap from thread */
187 rte_service_map_lcore_set(t->service_id, thread_id, 0);
189 /* service unregister */
190 rte_service_runstate_set(t->service_id, 0);
191 rte_service_component_runstate_set(t->service_id, 0);
192 rte_service_component_unregister(t->service_id);
194 t->service_id = UINT32_MAX;
198 * Pipeline is running when:
199 * (A) Pipeline is mapped to a data plane thread AND
200 * (B) Its data plane thread is in RUNNING state.
203 pipeline_is_running(struct pipeline *p)
208 return thread_is_running(p->thread_id);
212 * Main thread & data plane threads: message passing
214 enum thread_req_type {
215 THREAD_REQ_PIPELINE_ENABLE = 0,
216 THREAD_REQ_PIPELINE_DISABLE,
220 struct thread_msg_req {
221 enum thread_req_type type;
225 struct rte_pipeline *p;
227 struct rte_table_action *a;
228 } table[RTE_PIPELINE_TABLE_MAX];
229 struct rte_ring *msgq_req;
230 struct rte_ring *msgq_rsp;
231 uint32_t timer_period_ms;
236 struct rte_pipeline *p;
241 struct thread_msg_rsp {
248 static struct thread_msg_req *
249 thread_msg_alloc(void)
251 size_t size = RTE_MAX(sizeof(struct thread_msg_req),
252 sizeof(struct thread_msg_rsp));
254 return calloc(1, size);
258 thread_msg_free(struct thread_msg_rsp *rsp)
263 static struct thread_msg_rsp *
264 thread_msg_send_recv(struct pmd_internals *softnic,
266 struct thread_msg_req *req)
268 struct softnic_thread *t = &softnic->thread[thread_id];
269 struct rte_ring *msgq_req = t->msgq_req;
270 struct rte_ring *msgq_rsp = t->msgq_rsp;
271 struct thread_msg_rsp *rsp;
276 status = rte_ring_sp_enqueue(msgq_req, req);
277 } while (status == -ENOBUFS);
281 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
282 } while (status != 0);
288 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
290 const char *pipeline_name)
292 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
293 struct thread_msg_req *req;
294 struct thread_msg_rsp *rsp;
295 uint32_t n_pipelines, i;
298 /* Check input params */
299 if (!thread_is_valid(softnic, thread_id) ||
301 (p->n_ports_in == 0) ||
302 (p->n_ports_out == 0) ||
303 (p->n_tables == 0) ||
307 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
308 if (n_pipelines >= THREAD_PIPELINES_MAX)
311 if (softnic->params.sc && (n_pipelines == 0)) {
312 status = thread_sc_service_up(softnic, thread_id);
317 if (!thread_is_running(thread_id)) {
318 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
319 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
321 /* Data plane thread */
322 td->p[td->n_pipelines] = p->p;
325 for (i = 0; i < p->n_tables; i++)
326 tdp->table_data[i].a =
328 tdp->n_tables = p->n_tables;
330 tdp->msgq_req = p->msgq_req;
331 tdp->msgq_rsp = p->msgq_rsp;
332 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
333 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
338 p->thread_id = thread_id;
344 /* Allocate request */
345 req = thread_msg_alloc();
350 req->type = THREAD_REQ_PIPELINE_ENABLE;
351 req->pipeline_enable.p = p->p;
352 for (i = 0; i < p->n_tables; i++)
353 req->pipeline_enable.table[i].a =
355 req->pipeline_enable.msgq_req = p->msgq_req;
356 req->pipeline_enable.msgq_rsp = p->msgq_rsp;
357 req->pipeline_enable.timer_period_ms = p->timer_period_ms;
358 req->pipeline_enable.n_tables = p->n_tables;
360 /* Send request and wait for response */
361 rsp = thread_msg_send_recv(softnic, thread_id, req);
364 status = rsp->status;
367 thread_msg_free(rsp);
369 /* Request completion */
373 p->thread_id = thread_id;
380 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
382 const char *pipeline_name)
384 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
385 struct thread_msg_req *req;
386 struct thread_msg_rsp *rsp;
387 uint32_t n_pipelines;
390 /* Check input params */
391 if (!thread_is_valid(softnic, thread_id) ||
393 (p->enabled && (p->thread_id != thread_id)))
399 if (!thread_is_running(thread_id)) {
400 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
403 for (i = 0; i < td->n_pipelines; i++) {
404 struct pipeline_data *tdp = &td->pipeline_data[i];
409 /* Data plane thread */
410 if (i < td->n_pipelines - 1) {
411 struct rte_pipeline *pipeline_last =
412 td->p[td->n_pipelines - 1];
413 struct pipeline_data *tdp_last =
414 &td->pipeline_data[td->n_pipelines - 1];
416 td->p[i] = pipeline_last;
417 memcpy(tdp, tdp_last, sizeof(*tdp));
428 if (softnic->params.sc && (td->n_pipelines == 0))
429 thread_sc_service_down(softnic, thread_id);
434 /* Allocate request */
435 req = thread_msg_alloc();
440 req->type = THREAD_REQ_PIPELINE_DISABLE;
441 req->pipeline_disable.p = p->p;
443 /* Send request and wait for response */
444 rsp = thread_msg_send_recv(softnic, thread_id, req);
447 status = rsp->status;
450 thread_msg_free(rsp);
452 /* Request completion */
458 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
459 if (softnic->params.sc && (n_pipelines == 0))
460 thread_sc_service_down(softnic, thread_id);
466 * Data plane threads: message handling
468 static inline struct thread_msg_req *
469 thread_msg_recv(struct rte_ring *msgq_req)
471 struct thread_msg_req *req;
473 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
482 thread_msg_send(struct rte_ring *msgq_rsp,
483 struct thread_msg_rsp *rsp)
488 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
489 } while (status == -ENOBUFS);
492 static struct thread_msg_rsp *
493 thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
494 struct thread_msg_req *req)
496 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
497 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
501 t->p[t->n_pipelines] = req->pipeline_enable.p;
503 p->p = req->pipeline_enable.p;
504 for (i = 0; i < req->pipeline_enable.n_tables; i++)
506 req->pipeline_enable.table[i].a;
508 p->n_tables = req->pipeline_enable.n_tables;
510 p->msgq_req = req->pipeline_enable.msgq_req;
511 p->msgq_rsp = req->pipeline_enable.msgq_rsp;
513 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
514 p->time_next = rte_get_tsc_cycles() + p->timer_period;
523 static struct thread_msg_rsp *
524 thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
525 struct thread_msg_req *req)
527 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
528 uint32_t n_pipelines = t->n_pipelines;
529 struct rte_pipeline *pipeline = req->pipeline_disable.p;
533 for (i = 0; i < n_pipelines; i++) {
534 struct pipeline_data *p = &t->pipeline_data[i];
536 if (p->p != pipeline)
539 if (i < n_pipelines - 1) {
540 struct rte_pipeline *pipeline_last =
541 t->p[n_pipelines - 1];
542 struct pipeline_data *p_last =
543 &t->pipeline_data[n_pipelines - 1];
545 t->p[i] = pipeline_last;
546 memcpy(p, p_last, sizeof(*p));
555 /* should not get here */
561 thread_msg_handle(struct softnic_thread_data *t)
564 struct thread_msg_req *req;
565 struct thread_msg_rsp *rsp;
567 req = thread_msg_recv(t->msgq_req);
572 case THREAD_REQ_PIPELINE_ENABLE:
573 rsp = thread_msg_handle_pipeline_enable(t, req);
576 case THREAD_REQ_PIPELINE_DISABLE:
577 rsp = thread_msg_handle_pipeline_disable(t, req);
581 rsp = (struct thread_msg_rsp *)req;
585 thread_msg_send(t->msgq_rsp, rsp);
590 * Main thread & data plane threads: message passing
592 enum pipeline_req_type {
594 PIPELINE_REQ_PORT_IN_STATS_READ,
595 PIPELINE_REQ_PORT_IN_ENABLE,
596 PIPELINE_REQ_PORT_IN_DISABLE,
599 PIPELINE_REQ_PORT_OUT_STATS_READ,
602 PIPELINE_REQ_TABLE_STATS_READ,
603 PIPELINE_REQ_TABLE_RULE_ADD,
604 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
605 PIPELINE_REQ_TABLE_RULE_ADD_BULK,
606 PIPELINE_REQ_TABLE_RULE_DELETE,
607 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
608 PIPELINE_REQ_TABLE_RULE_STATS_READ,
609 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
610 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
611 PIPELINE_REQ_TABLE_RULE_MTR_READ,
612 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
613 PIPELINE_REQ_TABLE_RULE_TTL_READ,
617 struct pipeline_msg_req_port_in_stats_read {
621 struct pipeline_msg_req_port_out_stats_read {
625 struct pipeline_msg_req_table_stats_read {
629 struct pipeline_msg_req_table_rule_add {
630 struct softnic_table_rule_match match;
631 struct softnic_table_rule_action action;
634 struct pipeline_msg_req_table_rule_add_default {
635 struct softnic_table_rule_action action;
638 struct pipeline_msg_req_table_rule_add_bulk {
639 struct softnic_table_rule_match *match;
640 struct softnic_table_rule_action *action;
646 struct pipeline_msg_req_table_rule_delete {
647 struct softnic_table_rule_match match;
650 struct pipeline_msg_req_table_rule_stats_read {
655 struct pipeline_msg_req_table_mtr_profile_add {
656 uint32_t meter_profile_id;
657 struct rte_table_action_meter_profile profile;
660 struct pipeline_msg_req_table_mtr_profile_delete {
661 uint32_t meter_profile_id;
664 struct pipeline_msg_req_table_rule_mtr_read {
670 struct pipeline_msg_req_table_dscp_table_update {
672 struct rte_table_action_dscp_table dscp_table;
675 struct pipeline_msg_req_table_rule_ttl_read {
680 struct pipeline_msg_req {
681 enum pipeline_req_type type;
682 uint32_t id; /* Port IN, port OUT or table ID */
686 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
687 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
688 struct pipeline_msg_req_table_stats_read table_stats_read;
689 struct pipeline_msg_req_table_rule_add table_rule_add;
690 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
691 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
692 struct pipeline_msg_req_table_rule_delete table_rule_delete;
693 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
694 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
695 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
696 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
697 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
698 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
702 struct pipeline_msg_rsp_port_in_stats_read {
703 struct rte_pipeline_port_in_stats stats;
706 struct pipeline_msg_rsp_port_out_stats_read {
707 struct rte_pipeline_port_out_stats stats;
710 struct pipeline_msg_rsp_table_stats_read {
711 struct rte_pipeline_table_stats stats;
714 struct pipeline_msg_rsp_table_rule_add {
718 struct pipeline_msg_rsp_table_rule_add_default {
722 struct pipeline_msg_rsp_table_rule_add_bulk {
726 struct pipeline_msg_rsp_table_rule_stats_read {
727 struct rte_table_action_stats_counters stats;
730 struct pipeline_msg_rsp_table_rule_mtr_read {
731 struct rte_table_action_mtr_counters stats;
734 struct pipeline_msg_rsp_table_rule_ttl_read {
735 struct rte_table_action_ttl_counters stats;
738 struct pipeline_msg_rsp {
743 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
744 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
745 struct pipeline_msg_rsp_table_stats_read table_stats_read;
746 struct pipeline_msg_rsp_table_rule_add table_rule_add;
747 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
748 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
749 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
750 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
751 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
758 static struct pipeline_msg_req *
759 pipeline_msg_alloc(void)
761 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
762 sizeof(struct pipeline_msg_rsp));
764 return calloc(1, size);
768 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
773 static struct pipeline_msg_rsp *
774 pipeline_msg_send_recv(struct pipeline *p,
775 struct pipeline_msg_req *req)
777 struct rte_ring *msgq_req = p->msgq_req;
778 struct rte_ring *msgq_rsp = p->msgq_rsp;
779 struct pipeline_msg_rsp *rsp;
784 status = rte_ring_sp_enqueue(msgq_req, req);
785 } while (status == -ENOBUFS);
789 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
790 } while (status != 0);
796 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
797 const char *pipeline_name,
799 struct rte_pipeline_port_in_stats *stats,
803 struct pipeline_msg_req *req;
804 struct pipeline_msg_rsp *rsp;
807 /* Check input params */
808 if (pipeline_name == NULL ||
812 p = softnic_pipeline_find(softnic, pipeline_name);
814 port_id >= p->n_ports_in)
817 if (!pipeline_is_running(p)) {
818 status = rte_pipeline_port_in_stats_read(p->p,
826 /* Allocate request */
827 req = pipeline_msg_alloc();
832 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
834 req->port_in_stats_read.clear = clear;
836 /* Send request and wait for response */
837 rsp = pipeline_msg_send_recv(p, req);
840 status = rsp->status;
842 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
845 pipeline_msg_free(rsp);
851 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
852 const char *pipeline_name,
856 struct pipeline_msg_req *req;
857 struct pipeline_msg_rsp *rsp;
860 /* Check input params */
861 if (pipeline_name == NULL)
864 p = softnic_pipeline_find(softnic, pipeline_name);
866 port_id >= p->n_ports_in)
869 if (!pipeline_is_running(p)) {
870 status = rte_pipeline_port_in_enable(p->p, port_id);
874 /* Allocate request */
875 req = pipeline_msg_alloc();
880 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
883 /* Send request and wait for response */
884 rsp = pipeline_msg_send_recv(p, req);
887 status = rsp->status;
890 pipeline_msg_free(rsp);
896 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
897 const char *pipeline_name,
901 struct pipeline_msg_req *req;
902 struct pipeline_msg_rsp *rsp;
905 /* Check input params */
906 if (pipeline_name == NULL)
909 p = softnic_pipeline_find(softnic, pipeline_name);
911 port_id >= p->n_ports_in)
914 if (!pipeline_is_running(p)) {
915 status = rte_pipeline_port_in_disable(p->p, port_id);
919 /* Allocate request */
920 req = pipeline_msg_alloc();
925 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
928 /* Send request and wait for response */
929 rsp = pipeline_msg_send_recv(p, req);
932 status = rsp->status;
935 pipeline_msg_free(rsp);
941 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
942 const char *pipeline_name,
944 struct rte_pipeline_port_out_stats *stats,
948 struct pipeline_msg_req *req;
949 struct pipeline_msg_rsp *rsp;
952 /* Check input params */
953 if (pipeline_name == NULL ||
957 p = softnic_pipeline_find(softnic, pipeline_name);
959 port_id >= p->n_ports_out)
962 if (!pipeline_is_running(p)) {
963 status = rte_pipeline_port_out_stats_read(p->p,
971 /* Allocate request */
972 req = pipeline_msg_alloc();
977 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
979 req->port_out_stats_read.clear = clear;
981 /* Send request and wait for response */
982 rsp = pipeline_msg_send_recv(p, req);
985 status = rsp->status;
987 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
990 pipeline_msg_free(rsp);
996 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
997 const char *pipeline_name,
999 struct rte_pipeline_table_stats *stats,
1003 struct pipeline_msg_req *req;
1004 struct pipeline_msg_rsp *rsp;
1007 /* Check input params */
1008 if (pipeline_name == NULL ||
1012 p = softnic_pipeline_find(softnic, pipeline_name);
1014 table_id >= p->n_tables)
1017 if (!pipeline_is_running(p)) {
1018 status = rte_pipeline_table_stats_read(p->p,
1026 /* Allocate request */
1027 req = pipeline_msg_alloc();
1032 req->type = PIPELINE_REQ_TABLE_STATS_READ;
1034 req->table_stats_read.clear = clear;
1036 /* Send request and wait for response */
1037 rsp = pipeline_msg_send_recv(p, req);
1040 status = rsp->status;
1042 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
1045 pipeline_msg_free(rsp);
1051 match_check(struct softnic_table_rule_match *match,
1055 struct softnic_table *table;
1057 if (match == NULL ||
1059 table_id >= p->n_tables)
1062 table = &p->table[table_id];
1063 if (match->match_type != table->params.match_type)
1066 switch (match->match_type) {
1069 struct softnic_table_acl_params *t = &table->params.match.acl;
1070 struct softnic_table_rule_match_acl *r = &match->match.acl;
1072 if ((r->ip_version && (t->ip_version == 0)) ||
1073 ((r->ip_version == 0) && t->ip_version))
1076 if (r->ip_version) {
1077 if (r->sa_depth > 32 ||
1081 if (r->sa_depth > 128 ||
1096 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1097 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1099 if ((r->ip_version && (t->key_size != 4)) ||
1100 ((r->ip_version == 0) && (t->key_size != 16)))
1103 if (r->ip_version) {
1122 action_check(struct softnic_table_rule_action *action,
1126 struct softnic_table_action_profile *ap;
1128 if (action == NULL ||
1130 table_id >= p->n_tables)
1133 ap = p->table[table_id].ap;
1134 if (action->action_mask != ap->params.action_mask)
1137 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1138 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1139 action->fwd.id >= p->n_ports_out)
1142 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1143 action->fwd.id >= p->n_tables)
1147 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1148 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1149 uint32_t tc_mask1 = action->mtr.tc_mask;
1151 if (tc_mask1 != tc_mask0)
1155 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1156 uint32_t n_subports_per_port =
1157 ap->params.tm.n_subports_per_port;
1158 uint32_t n_pipes_per_subport =
1159 ap->params.tm.n_pipes_per_subport;
1160 uint32_t subport_id = action->tm.subport_id;
1161 uint32_t pipe_id = action->tm.pipe_id;
1163 if (subport_id >= n_subports_per_port ||
1164 pipe_id >= n_pipes_per_subport)
1168 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1169 uint64_t encap_mask = ap->params.encap.encap_mask;
1170 enum rte_table_action_encap_type type = action->encap.type;
1172 if ((encap_mask & (1LLU << type)) == 0)
1176 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1177 int ip_version0 = ap->params.common.ip_version;
1178 int ip_version1 = action->nat.ip_version;
1180 if ((ip_version1 && (ip_version0 == 0)) ||
1181 ((ip_version1 == 0) && ip_version0))
1189 action_default_check(struct softnic_table_rule_action *action,
1193 if (action == NULL ||
1194 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1196 table_id >= p->n_tables)
1199 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1200 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1201 action->fwd.id >= p->n_ports_out)
1204 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1205 action->fwd.id >= p->n_tables)
1212 union table_rule_match_low_level {
1213 struct rte_table_acl_rule_add_params acl_add;
1214 struct rte_table_acl_rule_delete_params acl_delete;
1215 struct rte_table_array_key array;
1216 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1217 struct rte_table_lpm_key lpm_ipv4;
1218 struct rte_table_lpm_ipv6_key lpm_ipv6;
1222 match_convert(struct softnic_table_rule_match *mh,
1223 union table_rule_match_low_level *ml,
1227 action_convert(struct rte_table_action *a,
1228 struct softnic_table_rule_action *action,
1229 struct rte_pipeline_table_entry *data);
1232 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1233 const char *pipeline_name,
1235 struct softnic_table_rule_match *match,
1236 struct softnic_table_rule_action *action,
1240 struct pipeline_msg_req *req;
1241 struct pipeline_msg_rsp *rsp;
1244 /* Check input params */
1245 if (pipeline_name == NULL ||
1251 p = softnic_pipeline_find(softnic, pipeline_name);
1253 table_id >= p->n_tables ||
1254 match_check(match, p, table_id) ||
1255 action_check(action, p, table_id))
1258 if (!pipeline_is_running(p)) {
1259 struct rte_table_action *a = p->table[table_id].a;
1260 union table_rule_match_low_level match_ll;
1261 struct rte_pipeline_table_entry *data_in, *data_out;
1265 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1269 /* Table match-action rule conversion */
1270 data_in = (struct rte_pipeline_table_entry *)buffer;
1272 status = match_convert(match, &match_ll, 1);
1278 status = action_convert(a, action, data_in);
1284 /* Add rule (match, action) to table */
1285 status = rte_pipeline_table_entry_add(p->p,
1296 /* Write Response */
1303 /* Allocate request */
1304 req = pipeline_msg_alloc();
1309 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1311 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1312 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1314 /* Send request and wait for response */
1315 rsp = pipeline_msg_send_recv(p, req);
1318 status = rsp->status;
1320 *data = rsp->table_rule_add.data;
1323 pipeline_msg_free(rsp);
1329 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1330 const char *pipeline_name,
1332 struct softnic_table_rule_action *action,
1336 struct pipeline_msg_req *req;
1337 struct pipeline_msg_rsp *rsp;
1340 /* Check input params */
1341 if (pipeline_name == NULL ||
1346 p = softnic_pipeline_find(softnic, pipeline_name);
1348 table_id >= p->n_tables ||
1349 action_default_check(action, p, table_id))
1352 if (!pipeline_is_running(p)) {
1353 struct rte_pipeline_table_entry *data_in, *data_out;
1356 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1361 data_in = (struct rte_pipeline_table_entry *)buffer;
1363 data_in->action = action->fwd.action;
1364 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1365 data_in->port_id = action->fwd.id;
1366 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1367 data_in->table_id = action->fwd.id;
1369 /* Add default rule to table */
1370 status = rte_pipeline_table_default_entry_add(p->p,
1379 /* Write Response */
1386 /* Allocate request */
1387 req = pipeline_msg_alloc();
1392 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1394 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1396 /* Send request and wait for response */
1397 rsp = pipeline_msg_send_recv(p, req);
1400 status = rsp->status;
1402 *data = rsp->table_rule_add_default.data;
1405 pipeline_msg_free(rsp);
1411 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1412 const char *pipeline_name,
1414 struct softnic_table_rule_match *match,
1415 struct softnic_table_rule_action *action,
1420 struct pipeline_msg_req *req;
1421 struct pipeline_msg_rsp *rsp;
1425 /* Check input params */
1426 if (pipeline_name == NULL ||
1434 p = softnic_pipeline_find(softnic, pipeline_name);
1436 table_id >= p->n_tables)
1439 for (i = 0; i < *n_rules; i++)
1440 if (match_check(match, p, table_id) ||
1441 action_check(action, p, table_id))
1444 if (!pipeline_is_running(p)) {
1445 struct rte_table_action *a = p->table[table_id].a;
1446 union table_rule_match_low_level *match_ll;
1448 void **match_ll_ptr;
1449 struct rte_pipeline_table_entry **action_ll_ptr;
1450 struct rte_pipeline_table_entry **entries_ptr =
1451 (struct rte_pipeline_table_entry **)data;
1453 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1456 /* Memory allocation */
1457 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1458 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1459 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1461 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1462 found = calloc(*n_rules, sizeof(int));
1464 if (match_ll == NULL ||
1465 action_ll == NULL ||
1466 match_ll_ptr == NULL ||
1467 action_ll_ptr == NULL ||
1471 for (i = 0; i < *n_rules; i++) {
1472 match_ll_ptr[i] = (void *)&match_ll[i];
1474 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1477 /* Rule match conversion */
1478 for (i = 0; i < *n_rules; i++) {
1479 status = match_convert(&match[i], match_ll_ptr[i], 1);
1484 /* Rule action conversion */
1485 for (i = 0; i < *n_rules; i++) {
1486 status = action_convert(a, &action[i], action_ll_ptr[i]);
1491 /* Add rule (match, action) to table */
1493 status = rte_pipeline_table_entry_add_bulk(p->p,
1503 for (i = 0; i < *n_rules; i++) {
1504 status = rte_pipeline_table_entry_add(p->p,
1519 free(action_ll_ptr);
1528 free(action_ll_ptr);
1537 /* Allocate request */
1538 req = pipeline_msg_alloc();
1543 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1545 req->table_rule_add_bulk.match = match;
1546 req->table_rule_add_bulk.action = action;
1547 req->table_rule_add_bulk.data = data;
1548 req->table_rule_add_bulk.n_rules = *n_rules;
1549 req->table_rule_add_bulk.bulk =
1550 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1552 /* Send request and wait for response */
1553 rsp = pipeline_msg_send_recv(p, req);
1556 status = rsp->status;
1558 *n_rules = rsp->table_rule_add_bulk.n_rules;
1561 pipeline_msg_free(rsp);
1567 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1568 const char *pipeline_name,
1570 struct softnic_table_rule_match *match)
1573 struct pipeline_msg_req *req;
1574 struct pipeline_msg_rsp *rsp;
1577 /* Check input params */
1578 if (pipeline_name == NULL ||
1582 p = softnic_pipeline_find(softnic, pipeline_name);
1584 table_id >= p->n_tables ||
1585 match_check(match, p, table_id))
1588 if (!pipeline_is_running(p)) {
1589 union table_rule_match_low_level match_ll;
1592 status = match_convert(match, &match_ll, 0);
1596 status = rte_pipeline_table_entry_delete(p->p,
1605 /* Allocate request */
1606 req = pipeline_msg_alloc();
1611 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1613 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1615 /* Send request and wait for response */
1616 rsp = pipeline_msg_send_recv(p, req);
1619 status = rsp->status;
1622 pipeline_msg_free(rsp);
1628 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1629 const char *pipeline_name,
1633 struct pipeline_msg_req *req;
1634 struct pipeline_msg_rsp *rsp;
1637 /* Check input params */
1638 if (pipeline_name == NULL)
1641 p = softnic_pipeline_find(softnic, pipeline_name);
1643 table_id >= p->n_tables)
1646 if (!pipeline_is_running(p)) {
1647 status = rte_pipeline_table_default_entry_delete(p->p,
1654 /* Allocate request */
1655 req = pipeline_msg_alloc();
1660 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1663 /* Send request and wait for response */
1664 rsp = pipeline_msg_send_recv(p, req);
1667 status = rsp->status;
1670 pipeline_msg_free(rsp);
1676 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1677 const char *pipeline_name,
1680 struct rte_table_action_stats_counters *stats,
1684 struct pipeline_msg_req *req;
1685 struct pipeline_msg_rsp *rsp;
1688 /* Check input params */
1689 if (pipeline_name == NULL ||
1694 p = softnic_pipeline_find(softnic, pipeline_name);
1696 table_id >= p->n_tables)
1699 if (!pipeline_is_running(p)) {
1700 struct rte_table_action *a = p->table[table_id].a;
1702 status = rte_table_action_stats_read(a,
1710 /* Allocate request */
1711 req = pipeline_msg_alloc();
1716 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1718 req->table_rule_stats_read.data = data;
1719 req->table_rule_stats_read.clear = clear;
1721 /* Send request and wait for response */
1722 rsp = pipeline_msg_send_recv(p, req);
1725 status = rsp->status;
1727 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1730 pipeline_msg_free(rsp);
1736 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1737 const char *pipeline_name,
1739 uint32_t meter_profile_id,
1740 struct rte_table_action_meter_profile *profile)
1743 struct pipeline_msg_req *req;
1744 struct pipeline_msg_rsp *rsp;
1745 struct softnic_table *table;
1746 struct softnic_table_meter_profile *mp;
1749 /* Check input params */
1750 if (pipeline_name == NULL ||
1754 p = softnic_pipeline_find(softnic, pipeline_name);
1756 table_id >= p->n_tables)
1759 table = &p->table[table_id];
1760 mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
1764 /* Resource Allocation */
1765 mp = calloc(1, sizeof(struct softnic_table_meter_profile));
1769 mp->meter_profile_id = meter_profile_id;
1770 memcpy(&mp->profile, profile, sizeof(mp->profile));
1772 if (!pipeline_is_running(p)) {
1773 status = rte_table_action_meter_profile_add(table->a,
1781 /* Add profile to the table. */
1782 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1787 /* Allocate request */
1788 req = pipeline_msg_alloc();
1795 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1797 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1798 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1800 /* Send request and wait for response */
1801 rsp = pipeline_msg_send_recv(p, req);
1804 status = rsp->status;
1806 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1811 pipeline_msg_free(rsp);
1817 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1818 const char *pipeline_name,
1820 uint32_t meter_profile_id)
1823 struct pipeline_msg_req *req;
1824 struct pipeline_msg_rsp *rsp;
1827 /* Check input params */
1828 if (pipeline_name == NULL)
1831 p = softnic_pipeline_find(softnic, pipeline_name);
1833 table_id >= p->n_tables)
1836 if (!pipeline_is_running(p)) {
1837 struct rte_table_action *a = p->table[table_id].a;
1839 status = rte_table_action_meter_profile_delete(a,
1845 /* Allocate request */
1846 req = pipeline_msg_alloc();
1851 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1853 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1855 /* Send request and wait for response */
1856 rsp = pipeline_msg_send_recv(p, req);
1859 status = rsp->status;
1862 pipeline_msg_free(rsp);
1868 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1869 const char *pipeline_name,
1873 struct rte_table_action_mtr_counters *stats,
1877 struct pipeline_msg_req *req;
1878 struct pipeline_msg_rsp *rsp;
1881 /* Check input params */
1882 if (pipeline_name == NULL ||
1887 p = softnic_pipeline_find(softnic, pipeline_name);
1889 table_id >= p->n_tables)
1892 if (!pipeline_is_running(p)) {
1893 struct rte_table_action *a = p->table[table_id].a;
1895 status = rte_table_action_meter_read(a,
1904 /* Allocate request */
1905 req = pipeline_msg_alloc();
1910 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1912 req->table_rule_mtr_read.data = data;
1913 req->table_rule_mtr_read.tc_mask = tc_mask;
1914 req->table_rule_mtr_read.clear = clear;
1916 /* Send request and wait for response */
1917 rsp = pipeline_msg_send_recv(p, req);
1920 status = rsp->status;
1922 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1925 pipeline_msg_free(rsp);
1931 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1932 const char *pipeline_name,
1935 struct rte_table_action_dscp_table *dscp_table)
1938 struct pipeline_msg_req *req;
1939 struct pipeline_msg_rsp *rsp;
1942 /* Check input params */
1943 if (pipeline_name == NULL ||
1947 p = softnic_pipeline_find(softnic, pipeline_name);
1949 table_id >= p->n_tables)
1952 if (!pipeline_is_running(p)) {
1953 struct rte_table_action *a = p->table[table_id].a;
1955 status = rte_table_action_dscp_table_update(a,
1959 /* Update table dscp table */
1961 memcpy(&p->table[table_id].dscp_table, dscp_table,
1962 sizeof(p->table[table_id].dscp_table));
1967 /* Allocate request */
1968 req = pipeline_msg_alloc();
1973 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
1975 req->table_dscp_table_update.dscp_mask = dscp_mask;
1976 memcpy(&req->table_dscp_table_update.dscp_table,
1977 dscp_table, sizeof(*dscp_table));
1979 /* Send request and wait for response */
1980 rsp = pipeline_msg_send_recv(p, req);
1983 status = rsp->status;
1985 /* Update table dscp table */
1987 memcpy(&p->table[table_id].dscp_table, dscp_table,
1988 sizeof(p->table[table_id].dscp_table));
1991 pipeline_msg_free(rsp);
1997 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
1998 const char *pipeline_name,
2001 struct rte_table_action_ttl_counters *stats,
2005 struct pipeline_msg_req *req;
2006 struct pipeline_msg_rsp *rsp;
2009 /* Check input params */
2010 if (pipeline_name == NULL ||
2015 p = softnic_pipeline_find(softnic, pipeline_name);
2017 table_id >= p->n_tables)
2020 if (!pipeline_is_running(p)) {
2021 struct rte_table_action *a = p->table[table_id].a;
2023 status = rte_table_action_ttl_read(a,
2031 /* Allocate request */
2032 req = pipeline_msg_alloc();
2037 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
2039 req->table_rule_ttl_read.data = data;
2040 req->table_rule_ttl_read.clear = clear;
2042 /* Send request and wait for response */
2043 rsp = pipeline_msg_send_recv(p, req);
2046 status = rsp->status;
2048 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2051 pipeline_msg_free(rsp);
2057 * Data plane threads: message handling
2059 static inline struct pipeline_msg_req *
2060 pipeline_msg_recv(struct rte_ring *msgq_req)
2062 struct pipeline_msg_req *req;
2064 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2073 pipeline_msg_send(struct rte_ring *msgq_rsp,
2074 struct pipeline_msg_rsp *rsp)
2079 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2080 } while (status == -ENOBUFS);
2083 static struct pipeline_msg_rsp *
2084 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2085 struct pipeline_msg_req *req)
2087 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2088 uint32_t port_id = req->id;
2089 int clear = req->port_in_stats_read.clear;
2091 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2093 &rsp->port_in_stats_read.stats,
2099 static struct pipeline_msg_rsp *
2100 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2101 struct pipeline_msg_req *req)
2103 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2104 uint32_t port_id = req->id;
2106 rsp->status = rte_pipeline_port_in_enable(p->p,
2112 static struct pipeline_msg_rsp *
2113 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2114 struct pipeline_msg_req *req)
2116 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2117 uint32_t port_id = req->id;
2119 rsp->status = rte_pipeline_port_in_disable(p->p,
2125 static struct pipeline_msg_rsp *
2126 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2127 struct pipeline_msg_req *req)
2129 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2130 uint32_t port_id = req->id;
2131 int clear = req->port_out_stats_read.clear;
2133 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2135 &rsp->port_out_stats_read.stats,
2141 static struct pipeline_msg_rsp *
2142 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2143 struct pipeline_msg_req *req)
2145 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2146 uint32_t port_id = req->id;
2147 int clear = req->table_stats_read.clear;
2149 rsp->status = rte_pipeline_table_stats_read(p->p,
2151 &rsp->table_stats_read.stats,
2158 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2163 switch (depth / 32) {
2173 depth32[1] = depth - 32;
2181 depth32[2] = depth - 64;
2189 depth32[3] = depth - 96;
2205 match_convert(struct softnic_table_rule_match *mh,
2206 union table_rule_match_low_level *ml,
2209 memset(ml, 0, sizeof(*ml));
2211 switch (mh->match_type) {
2213 if (mh->match.acl.ip_version)
2215 ml->acl_add.field_value[0].value.u8 =
2216 mh->match.acl.proto;
2217 ml->acl_add.field_value[0].mask_range.u8 =
2218 mh->match.acl.proto_mask;
2220 ml->acl_add.field_value[1].value.u32 =
2221 mh->match.acl.ipv4.sa;
2222 ml->acl_add.field_value[1].mask_range.u32 =
2223 mh->match.acl.sa_depth;
2225 ml->acl_add.field_value[2].value.u32 =
2226 mh->match.acl.ipv4.da;
2227 ml->acl_add.field_value[2].mask_range.u32 =
2228 mh->match.acl.da_depth;
2230 ml->acl_add.field_value[3].value.u16 =
2232 ml->acl_add.field_value[3].mask_range.u16 =
2235 ml->acl_add.field_value[4].value.u16 =
2237 ml->acl_add.field_value[4].mask_range.u16 =
2240 ml->acl_add.priority =
2241 (int32_t)mh->match.acl.priority;
2243 ml->acl_delete.field_value[0].value.u8 =
2244 mh->match.acl.proto;
2245 ml->acl_delete.field_value[0].mask_range.u8 =
2246 mh->match.acl.proto_mask;
2248 ml->acl_delete.field_value[1].value.u32 =
2249 mh->match.acl.ipv4.sa;
2250 ml->acl_delete.field_value[1].mask_range.u32 =
2251 mh->match.acl.sa_depth;
2253 ml->acl_delete.field_value[2].value.u32 =
2254 mh->match.acl.ipv4.da;
2255 ml->acl_delete.field_value[2].mask_range.u32 =
2256 mh->match.acl.da_depth;
2258 ml->acl_delete.field_value[3].value.u16 =
2260 ml->acl_delete.field_value[3].mask_range.u16 =
2263 ml->acl_delete.field_value[4].value.u16 =
2265 ml->acl_delete.field_value[4].mask_range.u16 =
2271 (uint32_t *)mh->match.acl.ipv6.sa;
2273 (uint32_t *)mh->match.acl.ipv6.da;
2274 uint32_t sa32_depth[4], da32_depth[4];
2277 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2282 status = match_convert_ipv6_depth(
2283 mh->match.acl.da_depth,
2288 ml->acl_add.field_value[0].value.u8 =
2289 mh->match.acl.proto;
2290 ml->acl_add.field_value[0].mask_range.u8 =
2291 mh->match.acl.proto_mask;
2293 ml->acl_add.field_value[1].value.u32 =
2294 rte_be_to_cpu_32(sa32[0]);
2295 ml->acl_add.field_value[1].mask_range.u32 =
2297 ml->acl_add.field_value[2].value.u32 =
2298 rte_be_to_cpu_32(sa32[1]);
2299 ml->acl_add.field_value[2].mask_range.u32 =
2301 ml->acl_add.field_value[3].value.u32 =
2302 rte_be_to_cpu_32(sa32[2]);
2303 ml->acl_add.field_value[3].mask_range.u32 =
2305 ml->acl_add.field_value[4].value.u32 =
2306 rte_be_to_cpu_32(sa32[3]);
2307 ml->acl_add.field_value[4].mask_range.u32 =
2310 ml->acl_add.field_value[5].value.u32 =
2311 rte_be_to_cpu_32(da32[0]);
2312 ml->acl_add.field_value[5].mask_range.u32 =
2314 ml->acl_add.field_value[6].value.u32 =
2315 rte_be_to_cpu_32(da32[1]);
2316 ml->acl_add.field_value[6].mask_range.u32 =
2318 ml->acl_add.field_value[7].value.u32 =
2319 rte_be_to_cpu_32(da32[2]);
2320 ml->acl_add.field_value[7].mask_range.u32 =
2322 ml->acl_add.field_value[8].value.u32 =
2323 rte_be_to_cpu_32(da32[3]);
2324 ml->acl_add.field_value[8].mask_range.u32 =
2327 ml->acl_add.field_value[9].value.u16 =
2329 ml->acl_add.field_value[9].mask_range.u16 =
2332 ml->acl_add.field_value[10].value.u16 =
2334 ml->acl_add.field_value[10].mask_range.u16 =
2337 ml->acl_add.priority =
2338 (int32_t)mh->match.acl.priority;
2341 (uint32_t *)mh->match.acl.ipv6.sa;
2343 (uint32_t *)mh->match.acl.ipv6.da;
2344 uint32_t sa32_depth[4], da32_depth[4];
2347 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2352 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2357 ml->acl_delete.field_value[0].value.u8 =
2358 mh->match.acl.proto;
2359 ml->acl_delete.field_value[0].mask_range.u8 =
2360 mh->match.acl.proto_mask;
2362 ml->acl_delete.field_value[1].value.u32 =
2363 rte_be_to_cpu_32(sa32[0]);
2364 ml->acl_delete.field_value[1].mask_range.u32 =
2366 ml->acl_delete.field_value[2].value.u32 =
2367 rte_be_to_cpu_32(sa32[1]);
2368 ml->acl_delete.field_value[2].mask_range.u32 =
2370 ml->acl_delete.field_value[3].value.u32 =
2371 rte_be_to_cpu_32(sa32[2]);
2372 ml->acl_delete.field_value[3].mask_range.u32 =
2374 ml->acl_delete.field_value[4].value.u32 =
2375 rte_be_to_cpu_32(sa32[3]);
2376 ml->acl_delete.field_value[4].mask_range.u32 =
2379 ml->acl_delete.field_value[5].value.u32 =
2380 rte_be_to_cpu_32(da32[0]);
2381 ml->acl_delete.field_value[5].mask_range.u32 =
2383 ml->acl_delete.field_value[6].value.u32 =
2384 rte_be_to_cpu_32(da32[1]);
2385 ml->acl_delete.field_value[6].mask_range.u32 =
2387 ml->acl_delete.field_value[7].value.u32 =
2388 rte_be_to_cpu_32(da32[2]);
2389 ml->acl_delete.field_value[7].mask_range.u32 =
2391 ml->acl_delete.field_value[8].value.u32 =
2392 rte_be_to_cpu_32(da32[3]);
2393 ml->acl_delete.field_value[8].mask_range.u32 =
2396 ml->acl_delete.field_value[9].value.u16 =
2398 ml->acl_delete.field_value[9].mask_range.u16 =
2401 ml->acl_delete.field_value[10].value.u16 =
2403 ml->acl_delete.field_value[10].mask_range.u16 =
2409 ml->array.pos = mh->match.array.pos;
2413 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2417 if (mh->match.lpm.ip_version) {
2418 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2419 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2421 memcpy(ml->lpm_ipv6.ip,
2422 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2423 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2434 action_convert(struct rte_table_action *a,
2435 struct softnic_table_rule_action *action,
2436 struct rte_pipeline_table_entry *data)
2441 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2442 status = rte_table_action_apply(a,
2444 RTE_TABLE_ACTION_FWD,
2451 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2452 status = rte_table_action_apply(a,
2454 RTE_TABLE_ACTION_LB,
2461 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2462 status = rte_table_action_apply(a,
2464 RTE_TABLE_ACTION_MTR,
2471 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2472 status = rte_table_action_apply(a,
2474 RTE_TABLE_ACTION_TM,
2481 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2482 status = rte_table_action_apply(a,
2484 RTE_TABLE_ACTION_ENCAP,
2491 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2492 status = rte_table_action_apply(a,
2494 RTE_TABLE_ACTION_NAT,
2501 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2502 status = rte_table_action_apply(a,
2504 RTE_TABLE_ACTION_TTL,
2511 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2512 status = rte_table_action_apply(a,
2514 RTE_TABLE_ACTION_STATS,
2521 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2522 status = rte_table_action_apply(a,
2524 RTE_TABLE_ACTION_TIME,
2531 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2532 status = rte_table_action_apply(a,
2534 RTE_TABLE_ACTION_TAG,
2541 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2542 status = rte_table_action_apply(a,
2544 RTE_TABLE_ACTION_DECAP,
2551 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2552 status = rte_table_action_apply(a,
2554 RTE_TABLE_ACTION_SYM_CRYPTO,
2555 &action->sym_crypto);
2564 static struct pipeline_msg_rsp *
2565 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2566 struct pipeline_msg_req *req)
2568 union table_rule_match_low_level match_ll;
2569 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2570 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2571 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2572 struct rte_pipeline_table_entry *data_in, *data_out;
2573 uint32_t table_id = req->id;
2574 int key_found, status;
2575 struct rte_table_action *a = p->table_data[table_id].a;
2578 memset(p->buffer, 0, sizeof(p->buffer));
2579 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2581 status = match_convert(match, &match_ll, 1);
2587 status = action_convert(a, action, data_in);
2593 status = rte_pipeline_table_entry_add(p->p,
2604 /* Write response */
2606 rsp->table_rule_add.data = data_out;
2611 static struct pipeline_msg_rsp *
2612 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2613 struct pipeline_msg_req *req)
2615 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2616 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2617 struct rte_pipeline_table_entry *data_in, *data_out;
2618 uint32_t table_id = req->id;
2622 memset(p->buffer, 0, sizeof(p->buffer));
2623 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2625 data_in->action = action->fwd.action;
2626 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2627 data_in->port_id = action->fwd.id;
2628 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2629 data_in->table_id = action->fwd.id;
2631 /* Add default rule to table */
2632 status = rte_pipeline_table_default_entry_add(p->p,
2641 /* Write response */
2643 rsp->table_rule_add_default.data = data_out;
2648 static struct pipeline_msg_rsp *
2649 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2650 struct pipeline_msg_req *req)
2652 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2654 uint32_t table_id = req->id;
2655 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2656 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2657 struct rte_pipeline_table_entry **data =
2658 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2659 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2660 uint32_t bulk = req->table_rule_add_bulk.bulk;
2662 struct rte_table_action *a = p->table_data[table_id].a;
2663 union table_rule_match_low_level *match_ll;
2665 void **match_ll_ptr;
2666 struct rte_pipeline_table_entry **action_ll_ptr;
2670 /* Memory allocation */
2671 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2672 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2673 match_ll_ptr = calloc(n_rules, sizeof(void *));
2675 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2676 found = calloc(n_rules, sizeof(int));
2678 if (match_ll == NULL ||
2679 action_ll == NULL ||
2680 match_ll_ptr == NULL ||
2681 action_ll_ptr == NULL ||
2685 for (i = 0; i < n_rules; i++) {
2686 match_ll_ptr[i] = (void *)&match_ll[i];
2688 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2691 /* Rule match conversion */
2692 for (i = 0; i < n_rules; i++) {
2693 status = match_convert(&match[i], match_ll_ptr[i], 1);
2698 /* Rule action conversion */
2699 for (i = 0; i < n_rules; i++) {
2700 status = action_convert(a, &action[i], action_ll_ptr[i]);
2705 /* Add rule (match, action) to table */
2707 status = rte_pipeline_table_entry_add_bulk(p->p,
2717 for (i = 0; i < n_rules; i++) {
2718 status = rte_pipeline_table_entry_add(p->p,
2731 /* Write response */
2733 rsp->table_rule_add_bulk.n_rules = n_rules;
2737 free(action_ll_ptr);
2746 free(action_ll_ptr);
2752 rsp->table_rule_add_bulk.n_rules = 0;
2756 static struct pipeline_msg_rsp *
2757 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2758 struct pipeline_msg_req *req)
2760 union table_rule_match_low_level match_ll;
2761 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2762 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2763 uint32_t table_id = req->id;
2764 int key_found, status;
2766 status = match_convert(match, &match_ll, 0);
2772 rsp->status = rte_pipeline_table_entry_delete(p->p,
2781 static struct pipeline_msg_rsp *
2782 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2783 struct pipeline_msg_req *req)
2785 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2786 uint32_t table_id = req->id;
2788 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2795 static struct pipeline_msg_rsp *
2796 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2797 struct pipeline_msg_req *req)
2799 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2800 uint32_t table_id = req->id;
2801 void *data = req->table_rule_stats_read.data;
2802 int clear = req->table_rule_stats_read.clear;
2803 struct rte_table_action *a = p->table_data[table_id].a;
2805 rsp->status = rte_table_action_stats_read(a,
2807 &rsp->table_rule_stats_read.stats,
2813 static struct pipeline_msg_rsp *
2814 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2815 struct pipeline_msg_req *req)
2817 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2818 uint32_t table_id = req->id;
2819 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2820 struct rte_table_action_meter_profile *profile =
2821 &req->table_mtr_profile_add.profile;
2822 struct rte_table_action *a = p->table_data[table_id].a;
2824 rsp->status = rte_table_action_meter_profile_add(a,
2831 static struct pipeline_msg_rsp *
2832 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2833 struct pipeline_msg_req *req)
2835 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2836 uint32_t table_id = req->id;
2837 uint32_t meter_profile_id =
2838 req->table_mtr_profile_delete.meter_profile_id;
2839 struct rte_table_action *a = p->table_data[table_id].a;
2841 rsp->status = rte_table_action_meter_profile_delete(a,
2847 static struct pipeline_msg_rsp *
2848 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2849 struct pipeline_msg_req *req)
2851 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2852 uint32_t table_id = req->id;
2853 void *data = req->table_rule_mtr_read.data;
2854 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2855 int clear = req->table_rule_mtr_read.clear;
2856 struct rte_table_action *a = p->table_data[table_id].a;
2858 rsp->status = rte_table_action_meter_read(a,
2861 &rsp->table_rule_mtr_read.stats,
2867 static struct pipeline_msg_rsp *
2868 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2869 struct pipeline_msg_req *req)
2871 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2872 uint32_t table_id = req->id;
2873 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2874 struct rte_table_action_dscp_table *dscp_table =
2875 &req->table_dscp_table_update.dscp_table;
2876 struct rte_table_action *a = p->table_data[table_id].a;
2878 rsp->status = rte_table_action_dscp_table_update(a,
2885 static struct pipeline_msg_rsp *
2886 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2887 struct pipeline_msg_req *req)
2889 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2890 uint32_t table_id = req->id;
2891 void *data = req->table_rule_ttl_read.data;
2892 int clear = req->table_rule_ttl_read.clear;
2893 struct rte_table_action *a = p->table_data[table_id].a;
2895 rsp->status = rte_table_action_ttl_read(a,
2897 &rsp->table_rule_ttl_read.stats,
2904 pipeline_msg_handle(struct pipeline_data *p)
2907 struct pipeline_msg_req *req;
2908 struct pipeline_msg_rsp *rsp;
2910 req = pipeline_msg_recv(p->msgq_req);
2914 switch (req->type) {
2915 case PIPELINE_REQ_PORT_IN_STATS_READ:
2916 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2919 case PIPELINE_REQ_PORT_IN_ENABLE:
2920 rsp = pipeline_msg_handle_port_in_enable(p, req);
2923 case PIPELINE_REQ_PORT_IN_DISABLE:
2924 rsp = pipeline_msg_handle_port_in_disable(p, req);
2927 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2928 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2931 case PIPELINE_REQ_TABLE_STATS_READ:
2932 rsp = pipeline_msg_handle_table_stats_read(p, req);
2935 case PIPELINE_REQ_TABLE_RULE_ADD:
2936 rsp = pipeline_msg_handle_table_rule_add(p, req);
2939 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2940 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2943 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2944 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2947 case PIPELINE_REQ_TABLE_RULE_DELETE:
2948 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2951 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2952 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2955 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2956 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2959 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2960 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
2963 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
2964 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
2967 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
2968 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
2971 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
2972 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
2975 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
2976 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
2980 rsp = (struct pipeline_msg_rsp *)req;
2984 pipeline_msg_send(p->msgq_rsp, rsp);
2989 * Data plane threads: main
2992 rte_pmd_softnic_run_internal(void *arg)
2994 struct rte_eth_dev *dev = arg;
2995 struct pmd_internals *softnic;
2996 struct softnic_thread_data *t;
2997 uint32_t thread_id, j;
2999 softnic = dev->data->dev_private;
3000 thread_id = rte_lcore_id();
3001 t = &softnic->thread_data[thread_id];
3005 for (j = 0; j < t->n_pipelines; j++)
3006 rte_pipeline_run(t->p[j]);
3009 if ((t->iter & 0xFLLU) == 0) {
3010 uint64_t time = rte_get_tsc_cycles();
3011 uint64_t time_next_min = UINT64_MAX;
3013 if (time < t->time_next_min)
3016 /* Pipeline message queues */
3017 for (j = 0; j < t->n_pipelines; j++) {
3018 struct pipeline_data *p =
3019 &t->pipeline_data[j];
3020 uint64_t time_next = p->time_next;
3022 if (time_next <= time) {
3023 pipeline_msg_handle(p);
3024 rte_pipeline_flush(p->p);
3025 time_next = time + p->timer_period;
3026 p->time_next = time_next;
3029 if (time_next < time_next_min)
3030 time_next_min = time_next;
3033 /* Thread message queues */
3035 uint64_t time_next = t->time_next;
3037 if (time_next <= time) {
3038 thread_msg_handle(t);
3039 time_next = time + t->timer_period;
3040 t->time_next = time_next;
3043 if (time_next < time_next_min)
3044 time_next_min = time_next;
3047 t->time_next_min = time_next_min;
3054 rte_pmd_softnic_run(uint16_t port_id)
3056 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3058 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
3059 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
3062 return (int)rte_pmd_softnic_run_internal(dev);