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];
32 rte_ring_free(t->msgq_req);
34 rte_ring_free(t->msgq_rsp);
39 softnic_thread_init(struct pmd_internals *softnic)
43 for (i = 0; i < RTE_MAX_LCORE; i++) {
44 char ring_name[NAME_MAX];
45 struct rte_ring *msgq_req, *msgq_rsp;
46 struct softnic_thread *t = &softnic->thread[i];
47 struct softnic_thread_data *t_data = &softnic->thread_data[i];
48 uint32_t cpu_id = rte_lcore_to_socket_id(i);
51 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ",
55 msgq_req = rte_ring_create(ring_name,
58 RING_F_SP_ENQ | RING_F_SC_DEQ);
60 if (msgq_req == NULL) {
61 softnic_thread_free(softnic);
65 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP",
69 msgq_rsp = rte_ring_create(ring_name,
72 RING_F_SP_ENQ | RING_F_SC_DEQ);
74 if (msgq_rsp == NULL) {
75 softnic_thread_free(softnic);
79 /* Main thread records */
80 t->msgq_req = msgq_req;
81 t->msgq_rsp = msgq_rsp;
82 t->service_id = UINT32_MAX;
84 /* Data plane thread records */
85 t_data->n_pipelines = 0;
86 t_data->msgq_req = msgq_req;
87 t_data->msgq_rsp = msgq_rsp;
88 t_data->timer_period =
89 (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
90 t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
91 t_data->time_next_min = t_data->time_next;
98 thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id)
100 if (thread_id == rte_get_main_lcore())
101 return 0; /* FALSE */
103 if (softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_SERVICE))
105 if (!softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_RTE))
108 return 0; /* FALSE */
112 thread_is_running(uint32_t thread_id)
114 enum rte_lcore_state_t thread_state;
116 thread_state = rte_eal_get_lcore_state(thread_id);
117 return (thread_state == RUNNING)? 1 : 0;
121 rte_pmd_softnic_run_internal(void *arg);
124 thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
126 struct rte_service_spec service_params;
127 struct softnic_thread *t = &softnic->thread[thread_id];
128 struct rte_eth_dev *dev;
132 dev = rte_eth_dev_get_by_name(softnic->params.name);
136 snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
137 softnic->params.name,
139 service_params.callback = rte_pmd_softnic_run_internal;
140 service_params.callback_userdata = dev;
141 service_params.capabilities = 0;
142 service_params.socket_id = (int)softnic->params.cpu_id;
144 /* service register */
145 status = rte_service_component_register(&service_params, &t->service_id);
149 status = rte_service_component_runstate_set(t->service_id, 1);
151 rte_service_component_unregister(t->service_id);
152 t->service_id = UINT32_MAX;
156 status = rte_service_runstate_set(t->service_id, 1);
158 rte_service_component_runstate_set(t->service_id, 0);
159 rte_service_component_unregister(t->service_id);
160 t->service_id = UINT32_MAX;
164 /* service map to thread */
165 status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
167 rte_service_runstate_set(t->service_id, 0);
168 rte_service_component_runstate_set(t->service_id, 0);
169 rte_service_component_unregister(t->service_id);
170 t->service_id = UINT32_MAX;
178 thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
180 struct softnic_thread *t = &softnic->thread[thread_id];
182 /* service unmap from thread */
183 rte_service_map_lcore_set(t->service_id, thread_id, 0);
185 /* service unregister */
186 rte_service_runstate_set(t->service_id, 0);
187 rte_service_component_runstate_set(t->service_id, 0);
188 rte_service_component_unregister(t->service_id);
190 t->service_id = UINT32_MAX;
194 * Pipeline is running when:
195 * (A) Pipeline is mapped to a data plane thread AND
196 * (B) Its data plane thread is in RUNNING state.
199 pipeline_is_running(struct pipeline *p)
204 return thread_is_running(p->thread_id);
208 * Main thread & data plane threads: message passing
210 enum thread_req_type {
211 THREAD_REQ_PIPELINE_ENABLE = 0,
212 THREAD_REQ_PIPELINE_DISABLE,
216 struct thread_msg_req {
217 enum thread_req_type type;
221 struct rte_pipeline *p;
223 struct rte_table_action *a;
224 } table[RTE_PIPELINE_TABLE_MAX];
225 struct rte_ring *msgq_req;
226 struct rte_ring *msgq_rsp;
227 uint32_t timer_period_ms;
232 struct rte_pipeline *p;
237 struct thread_msg_rsp {
244 static struct thread_msg_req *
245 thread_msg_alloc(void)
247 size_t size = RTE_MAX(sizeof(struct thread_msg_req),
248 sizeof(struct thread_msg_rsp));
250 return calloc(1, size);
254 thread_msg_free(struct thread_msg_rsp *rsp)
259 static struct thread_msg_rsp *
260 thread_msg_send_recv(struct pmd_internals *softnic,
262 struct thread_msg_req *req)
264 struct softnic_thread *t = &softnic->thread[thread_id];
265 struct rte_ring *msgq_req = t->msgq_req;
266 struct rte_ring *msgq_rsp = t->msgq_rsp;
267 struct thread_msg_rsp *rsp;
272 status = rte_ring_sp_enqueue(msgq_req, req);
273 } while (status == -ENOBUFS);
277 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
278 } while (status != 0);
284 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
286 const char *pipeline_name)
288 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
289 struct thread_msg_req *req;
290 struct thread_msg_rsp *rsp;
291 uint32_t n_pipelines, i;
294 /* Check input params */
295 if (!thread_is_valid(softnic, thread_id) ||
297 (p->n_ports_in == 0) ||
298 (p->n_ports_out == 0) ||
299 (p->n_tables == 0) ||
303 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
304 if (n_pipelines >= THREAD_PIPELINES_MAX)
307 if (softnic->params.sc && (n_pipelines == 0)) {
308 status = thread_sc_service_up(softnic, thread_id);
313 if (!thread_is_running(thread_id)) {
314 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
315 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
317 /* Data plane thread */
318 td->p[td->n_pipelines] = p->p;
321 for (i = 0; i < p->n_tables; i++)
322 tdp->table_data[i].a =
324 tdp->n_tables = p->n_tables;
326 tdp->msgq_req = p->msgq_req;
327 tdp->msgq_rsp = p->msgq_rsp;
328 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
329 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
334 p->thread_id = thread_id;
340 /* Allocate request */
341 req = thread_msg_alloc();
346 req->type = THREAD_REQ_PIPELINE_ENABLE;
347 req->pipeline_enable.p = p->p;
348 for (i = 0; i < p->n_tables; i++)
349 req->pipeline_enable.table[i].a =
351 req->pipeline_enable.msgq_req = p->msgq_req;
352 req->pipeline_enable.msgq_rsp = p->msgq_rsp;
353 req->pipeline_enable.timer_period_ms = p->timer_period_ms;
354 req->pipeline_enable.n_tables = p->n_tables;
356 /* Send request and wait for response */
357 rsp = thread_msg_send_recv(softnic, thread_id, req);
360 status = rsp->status;
363 thread_msg_free(rsp);
365 /* Request completion */
369 p->thread_id = thread_id;
376 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
378 const char *pipeline_name)
380 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
381 struct thread_msg_req *req;
382 struct thread_msg_rsp *rsp;
383 uint32_t n_pipelines;
386 /* Check input params */
387 if (!thread_is_valid(softnic, thread_id) ||
389 (p->enabled && (p->thread_id != thread_id)))
395 if (!thread_is_running(thread_id)) {
396 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
399 for (i = 0; i < td->n_pipelines; i++) {
400 struct pipeline_data *tdp = &td->pipeline_data[i];
405 /* Data plane thread */
406 if (i < td->n_pipelines - 1) {
407 struct rte_pipeline *pipeline_last =
408 td->p[td->n_pipelines - 1];
409 struct pipeline_data *tdp_last =
410 &td->pipeline_data[td->n_pipelines - 1];
412 td->p[i] = pipeline_last;
413 memcpy(tdp, tdp_last, sizeof(*tdp));
424 if (softnic->params.sc && (td->n_pipelines == 0))
425 thread_sc_service_down(softnic, thread_id);
430 /* Allocate request */
431 req = thread_msg_alloc();
436 req->type = THREAD_REQ_PIPELINE_DISABLE;
437 req->pipeline_disable.p = p->p;
439 /* Send request and wait for response */
440 rsp = thread_msg_send_recv(softnic, thread_id, req);
443 status = rsp->status;
446 thread_msg_free(rsp);
448 /* Request completion */
454 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
455 if (softnic->params.sc && (n_pipelines == 0))
456 thread_sc_service_down(softnic, thread_id);
462 * Data plane threads: message handling
464 static inline struct thread_msg_req *
465 thread_msg_recv(struct rte_ring *msgq_req)
467 struct thread_msg_req *req;
469 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
478 thread_msg_send(struct rte_ring *msgq_rsp,
479 struct thread_msg_rsp *rsp)
484 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
485 } while (status == -ENOBUFS);
488 static struct thread_msg_rsp *
489 thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
490 struct thread_msg_req *req)
492 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
493 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
497 t->p[t->n_pipelines] = req->pipeline_enable.p;
499 p->p = req->pipeline_enable.p;
500 for (i = 0; i < req->pipeline_enable.n_tables; i++)
502 req->pipeline_enable.table[i].a;
504 p->n_tables = req->pipeline_enable.n_tables;
506 p->msgq_req = req->pipeline_enable.msgq_req;
507 p->msgq_rsp = req->pipeline_enable.msgq_rsp;
509 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
510 p->time_next = rte_get_tsc_cycles() + p->timer_period;
519 static struct thread_msg_rsp *
520 thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
521 struct thread_msg_req *req)
523 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
524 uint32_t n_pipelines = t->n_pipelines;
525 struct rte_pipeline *pipeline = req->pipeline_disable.p;
529 for (i = 0; i < n_pipelines; i++) {
530 struct pipeline_data *p = &t->pipeline_data[i];
532 if (p->p != pipeline)
535 if (i < n_pipelines - 1) {
536 struct rte_pipeline *pipeline_last =
537 t->p[n_pipelines - 1];
538 struct pipeline_data *p_last =
539 &t->pipeline_data[n_pipelines - 1];
541 t->p[i] = pipeline_last;
542 memcpy(p, p_last, sizeof(*p));
551 /* should not get here */
557 thread_msg_handle(struct softnic_thread_data *t)
560 struct thread_msg_req *req;
561 struct thread_msg_rsp *rsp;
563 req = thread_msg_recv(t->msgq_req);
568 case THREAD_REQ_PIPELINE_ENABLE:
569 rsp = thread_msg_handle_pipeline_enable(t, req);
572 case THREAD_REQ_PIPELINE_DISABLE:
573 rsp = thread_msg_handle_pipeline_disable(t, req);
577 rsp = (struct thread_msg_rsp *)req;
581 thread_msg_send(t->msgq_rsp, rsp);
586 * Main thread & data plane threads: message passing
588 enum pipeline_req_type {
590 PIPELINE_REQ_PORT_IN_STATS_READ,
591 PIPELINE_REQ_PORT_IN_ENABLE,
592 PIPELINE_REQ_PORT_IN_DISABLE,
595 PIPELINE_REQ_PORT_OUT_STATS_READ,
598 PIPELINE_REQ_TABLE_STATS_READ,
599 PIPELINE_REQ_TABLE_RULE_ADD,
600 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
601 PIPELINE_REQ_TABLE_RULE_ADD_BULK,
602 PIPELINE_REQ_TABLE_RULE_DELETE,
603 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
604 PIPELINE_REQ_TABLE_RULE_STATS_READ,
605 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
606 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
607 PIPELINE_REQ_TABLE_RULE_MTR_READ,
608 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
609 PIPELINE_REQ_TABLE_RULE_TTL_READ,
613 struct pipeline_msg_req_port_in_stats_read {
617 struct pipeline_msg_req_port_out_stats_read {
621 struct pipeline_msg_req_table_stats_read {
625 struct pipeline_msg_req_table_rule_add {
626 struct softnic_table_rule_match match;
627 struct softnic_table_rule_action action;
630 struct pipeline_msg_req_table_rule_add_default {
631 struct softnic_table_rule_action action;
634 struct pipeline_msg_req_table_rule_add_bulk {
635 struct softnic_table_rule_match *match;
636 struct softnic_table_rule_action *action;
642 struct pipeline_msg_req_table_rule_delete {
643 struct softnic_table_rule_match match;
646 struct pipeline_msg_req_table_rule_stats_read {
651 struct pipeline_msg_req_table_mtr_profile_add {
652 uint32_t meter_profile_id;
653 struct rte_table_action_meter_profile profile;
656 struct pipeline_msg_req_table_mtr_profile_delete {
657 uint32_t meter_profile_id;
660 struct pipeline_msg_req_table_rule_mtr_read {
666 struct pipeline_msg_req_table_dscp_table_update {
668 struct rte_table_action_dscp_table dscp_table;
671 struct pipeline_msg_req_table_rule_ttl_read {
676 struct pipeline_msg_req {
677 enum pipeline_req_type type;
678 uint32_t id; /* Port IN, port OUT or table ID */
682 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
683 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
684 struct pipeline_msg_req_table_stats_read table_stats_read;
685 struct pipeline_msg_req_table_rule_add table_rule_add;
686 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
687 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
688 struct pipeline_msg_req_table_rule_delete table_rule_delete;
689 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
690 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
691 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
692 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
693 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
694 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
698 struct pipeline_msg_rsp_port_in_stats_read {
699 struct rte_pipeline_port_in_stats stats;
702 struct pipeline_msg_rsp_port_out_stats_read {
703 struct rte_pipeline_port_out_stats stats;
706 struct pipeline_msg_rsp_table_stats_read {
707 struct rte_pipeline_table_stats stats;
710 struct pipeline_msg_rsp_table_rule_add {
714 struct pipeline_msg_rsp_table_rule_add_default {
718 struct pipeline_msg_rsp_table_rule_add_bulk {
722 struct pipeline_msg_rsp_table_rule_stats_read {
723 struct rte_table_action_stats_counters stats;
726 struct pipeline_msg_rsp_table_rule_mtr_read {
727 struct rte_table_action_mtr_counters stats;
730 struct pipeline_msg_rsp_table_rule_ttl_read {
731 struct rte_table_action_ttl_counters stats;
734 struct pipeline_msg_rsp {
739 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
740 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
741 struct pipeline_msg_rsp_table_stats_read table_stats_read;
742 struct pipeline_msg_rsp_table_rule_add table_rule_add;
743 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
744 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
745 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
746 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
747 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
754 static struct pipeline_msg_req *
755 pipeline_msg_alloc(void)
757 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
758 sizeof(struct pipeline_msg_rsp));
760 return calloc(1, size);
764 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
769 static struct pipeline_msg_rsp *
770 pipeline_msg_send_recv(struct pipeline *p,
771 struct pipeline_msg_req *req)
773 struct rte_ring *msgq_req = p->msgq_req;
774 struct rte_ring *msgq_rsp = p->msgq_rsp;
775 struct pipeline_msg_rsp *rsp;
780 status = rte_ring_sp_enqueue(msgq_req, req);
781 } while (status == -ENOBUFS);
785 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
786 } while (status != 0);
792 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
793 const char *pipeline_name,
795 struct rte_pipeline_port_in_stats *stats,
799 struct pipeline_msg_req *req;
800 struct pipeline_msg_rsp *rsp;
803 /* Check input params */
804 if (pipeline_name == NULL ||
808 p = softnic_pipeline_find(softnic, pipeline_name);
810 port_id >= p->n_ports_in)
813 if (!pipeline_is_running(p)) {
814 status = rte_pipeline_port_in_stats_read(p->p,
822 /* Allocate request */
823 req = pipeline_msg_alloc();
828 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
830 req->port_in_stats_read.clear = clear;
832 /* Send request and wait for response */
833 rsp = pipeline_msg_send_recv(p, req);
836 status = rsp->status;
838 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
841 pipeline_msg_free(rsp);
847 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
848 const char *pipeline_name,
852 struct pipeline_msg_req *req;
853 struct pipeline_msg_rsp *rsp;
856 /* Check input params */
857 if (pipeline_name == NULL)
860 p = softnic_pipeline_find(softnic, pipeline_name);
862 port_id >= p->n_ports_in)
865 if (!pipeline_is_running(p)) {
866 status = rte_pipeline_port_in_enable(p->p, port_id);
870 /* Allocate request */
871 req = pipeline_msg_alloc();
876 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
879 /* Send request and wait for response */
880 rsp = pipeline_msg_send_recv(p, req);
883 status = rsp->status;
886 pipeline_msg_free(rsp);
892 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
893 const char *pipeline_name,
897 struct pipeline_msg_req *req;
898 struct pipeline_msg_rsp *rsp;
901 /* Check input params */
902 if (pipeline_name == NULL)
905 p = softnic_pipeline_find(softnic, pipeline_name);
907 port_id >= p->n_ports_in)
910 if (!pipeline_is_running(p)) {
911 status = rte_pipeline_port_in_disable(p->p, port_id);
915 /* Allocate request */
916 req = pipeline_msg_alloc();
921 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
924 /* Send request and wait for response */
925 rsp = pipeline_msg_send_recv(p, req);
928 status = rsp->status;
931 pipeline_msg_free(rsp);
937 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
938 const char *pipeline_name,
940 struct rte_pipeline_port_out_stats *stats,
944 struct pipeline_msg_req *req;
945 struct pipeline_msg_rsp *rsp;
948 /* Check input params */
949 if (pipeline_name == NULL ||
953 p = softnic_pipeline_find(softnic, pipeline_name);
955 port_id >= p->n_ports_out)
958 if (!pipeline_is_running(p)) {
959 status = rte_pipeline_port_out_stats_read(p->p,
967 /* Allocate request */
968 req = pipeline_msg_alloc();
973 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
975 req->port_out_stats_read.clear = clear;
977 /* Send request and wait for response */
978 rsp = pipeline_msg_send_recv(p, req);
981 status = rsp->status;
983 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
986 pipeline_msg_free(rsp);
992 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
993 const char *pipeline_name,
995 struct rte_pipeline_table_stats *stats,
999 struct pipeline_msg_req *req;
1000 struct pipeline_msg_rsp *rsp;
1003 /* Check input params */
1004 if (pipeline_name == NULL ||
1008 p = softnic_pipeline_find(softnic, pipeline_name);
1010 table_id >= p->n_tables)
1013 if (!pipeline_is_running(p)) {
1014 status = rte_pipeline_table_stats_read(p->p,
1022 /* Allocate request */
1023 req = pipeline_msg_alloc();
1028 req->type = PIPELINE_REQ_TABLE_STATS_READ;
1030 req->table_stats_read.clear = clear;
1032 /* Send request and wait for response */
1033 rsp = pipeline_msg_send_recv(p, req);
1036 status = rsp->status;
1038 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
1041 pipeline_msg_free(rsp);
1047 match_check(struct softnic_table_rule_match *match,
1051 struct softnic_table *table;
1053 if (match == NULL ||
1055 table_id >= p->n_tables)
1058 table = &p->table[table_id];
1059 if (match->match_type != table->params.match_type)
1062 switch (match->match_type) {
1065 struct softnic_table_acl_params *t = &table->params.match.acl;
1066 struct softnic_table_rule_match_acl *r = &match->match.acl;
1068 if ((r->ip_version && (t->ip_version == 0)) ||
1069 ((r->ip_version == 0) && t->ip_version))
1072 if (r->ip_version) {
1073 if (r->sa_depth > 32 ||
1077 if (r->sa_depth > 128 ||
1092 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1093 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1095 if ((r->ip_version && (t->key_size != 4)) ||
1096 ((r->ip_version == 0) && (t->key_size != 16)))
1099 if (r->ip_version) {
1118 action_check(struct softnic_table_rule_action *action,
1122 struct softnic_table_action_profile *ap;
1124 if (action == NULL ||
1126 table_id >= p->n_tables)
1129 ap = p->table[table_id].ap;
1130 if (action->action_mask != ap->params.action_mask)
1133 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1134 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1135 action->fwd.id >= p->n_ports_out)
1138 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1139 action->fwd.id >= p->n_tables)
1143 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1144 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1145 uint32_t tc_mask1 = action->mtr.tc_mask;
1147 if (tc_mask1 != tc_mask0)
1151 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1152 uint32_t n_subports_per_port =
1153 ap->params.tm.n_subports_per_port;
1154 uint32_t n_pipes_per_subport =
1155 ap->params.tm.n_pipes_per_subport;
1156 uint32_t subport_id = action->tm.subport_id;
1157 uint32_t pipe_id = action->tm.pipe_id;
1159 if (subport_id >= n_subports_per_port ||
1160 pipe_id >= n_pipes_per_subport)
1164 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1165 uint64_t encap_mask = ap->params.encap.encap_mask;
1166 enum rte_table_action_encap_type type = action->encap.type;
1168 if ((encap_mask & (1LLU << type)) == 0)
1172 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1173 int ip_version0 = ap->params.common.ip_version;
1174 int ip_version1 = action->nat.ip_version;
1176 if ((ip_version1 && (ip_version0 == 0)) ||
1177 ((ip_version1 == 0) && ip_version0))
1185 action_default_check(struct softnic_table_rule_action *action,
1189 if (action == NULL ||
1190 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1192 table_id >= p->n_tables)
1195 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1196 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1197 action->fwd.id >= p->n_ports_out)
1200 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1201 action->fwd.id >= p->n_tables)
1208 union table_rule_match_low_level {
1209 struct rte_table_acl_rule_add_params acl_add;
1210 struct rte_table_acl_rule_delete_params acl_delete;
1211 struct rte_table_array_key array;
1212 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1213 struct rte_table_lpm_key lpm_ipv4;
1214 struct rte_table_lpm_ipv6_key lpm_ipv6;
1218 match_convert(struct softnic_table_rule_match *mh,
1219 union table_rule_match_low_level *ml,
1223 action_convert(struct rte_table_action *a,
1224 struct softnic_table_rule_action *action,
1225 struct rte_pipeline_table_entry *data);
1228 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1229 const char *pipeline_name,
1231 struct softnic_table_rule_match *match,
1232 struct softnic_table_rule_action *action,
1236 struct pipeline_msg_req *req;
1237 struct pipeline_msg_rsp *rsp;
1240 /* Check input params */
1241 if (pipeline_name == NULL ||
1247 p = softnic_pipeline_find(softnic, pipeline_name);
1249 table_id >= p->n_tables ||
1250 match_check(match, p, table_id) ||
1251 action_check(action, p, table_id))
1254 if (!pipeline_is_running(p)) {
1255 struct rte_table_action *a = p->table[table_id].a;
1256 union table_rule_match_low_level match_ll;
1257 struct rte_pipeline_table_entry *data_in, *data_out;
1261 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1265 /* Table match-action rule conversion */
1266 data_in = (struct rte_pipeline_table_entry *)buffer;
1268 status = match_convert(match, &match_ll, 1);
1274 status = action_convert(a, action, data_in);
1280 /* Add rule (match, action) to table */
1281 status = rte_pipeline_table_entry_add(p->p,
1292 /* Write Response */
1299 /* Allocate request */
1300 req = pipeline_msg_alloc();
1305 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1307 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1308 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1310 /* Send request and wait for response */
1311 rsp = pipeline_msg_send_recv(p, req);
1314 status = rsp->status;
1316 *data = rsp->table_rule_add.data;
1319 pipeline_msg_free(rsp);
1325 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1326 const char *pipeline_name,
1328 struct softnic_table_rule_action *action,
1332 struct pipeline_msg_req *req;
1333 struct pipeline_msg_rsp *rsp;
1336 /* Check input params */
1337 if (pipeline_name == NULL ||
1342 p = softnic_pipeline_find(softnic, pipeline_name);
1344 table_id >= p->n_tables ||
1345 action_default_check(action, p, table_id))
1348 if (!pipeline_is_running(p)) {
1349 struct rte_pipeline_table_entry *data_in, *data_out;
1352 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1357 data_in = (struct rte_pipeline_table_entry *)buffer;
1359 data_in->action = action->fwd.action;
1360 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1361 data_in->port_id = action->fwd.id;
1362 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1363 data_in->table_id = action->fwd.id;
1365 /* Add default rule to table */
1366 status = rte_pipeline_table_default_entry_add(p->p,
1375 /* Write Response */
1382 /* Allocate request */
1383 req = pipeline_msg_alloc();
1388 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1390 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1392 /* Send request and wait for response */
1393 rsp = pipeline_msg_send_recv(p, req);
1396 status = rsp->status;
1398 *data = rsp->table_rule_add_default.data;
1401 pipeline_msg_free(rsp);
1407 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1408 const char *pipeline_name,
1410 struct softnic_table_rule_match *match,
1411 struct softnic_table_rule_action *action,
1416 struct pipeline_msg_req *req;
1417 struct pipeline_msg_rsp *rsp;
1421 /* Check input params */
1422 if (pipeline_name == NULL ||
1430 p = softnic_pipeline_find(softnic, pipeline_name);
1432 table_id >= p->n_tables)
1435 for (i = 0; i < *n_rules; i++)
1436 if (match_check(match, p, table_id) ||
1437 action_check(action, p, table_id))
1440 if (!pipeline_is_running(p)) {
1441 struct rte_table_action *a = p->table[table_id].a;
1442 union table_rule_match_low_level *match_ll;
1444 void **match_ll_ptr;
1445 struct rte_pipeline_table_entry **action_ll_ptr;
1446 struct rte_pipeline_table_entry **entries_ptr =
1447 (struct rte_pipeline_table_entry **)data;
1449 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1452 /* Memory allocation */
1453 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1454 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1455 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1457 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1458 found = calloc(*n_rules, sizeof(int));
1460 if (match_ll == NULL ||
1461 action_ll == NULL ||
1462 match_ll_ptr == NULL ||
1463 action_ll_ptr == NULL ||
1467 for (i = 0; i < *n_rules; i++) {
1468 match_ll_ptr[i] = (void *)&match_ll[i];
1470 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1473 /* Rule match conversion */
1474 for (i = 0; i < *n_rules; i++) {
1475 status = match_convert(&match[i], match_ll_ptr[i], 1);
1480 /* Rule action conversion */
1481 for (i = 0; i < *n_rules; i++) {
1482 status = action_convert(a, &action[i], action_ll_ptr[i]);
1487 /* Add rule (match, action) to table */
1489 status = rte_pipeline_table_entry_add_bulk(p->p,
1499 for (i = 0; i < *n_rules; i++) {
1500 status = rte_pipeline_table_entry_add(p->p,
1515 free(action_ll_ptr);
1524 free(action_ll_ptr);
1533 /* Allocate request */
1534 req = pipeline_msg_alloc();
1539 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1541 req->table_rule_add_bulk.match = match;
1542 req->table_rule_add_bulk.action = action;
1543 req->table_rule_add_bulk.data = data;
1544 req->table_rule_add_bulk.n_rules = *n_rules;
1545 req->table_rule_add_bulk.bulk =
1546 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1548 /* Send request and wait for response */
1549 rsp = pipeline_msg_send_recv(p, req);
1552 status = rsp->status;
1554 *n_rules = rsp->table_rule_add_bulk.n_rules;
1557 pipeline_msg_free(rsp);
1563 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1564 const char *pipeline_name,
1566 struct softnic_table_rule_match *match)
1569 struct pipeline_msg_req *req;
1570 struct pipeline_msg_rsp *rsp;
1573 /* Check input params */
1574 if (pipeline_name == NULL ||
1578 p = softnic_pipeline_find(softnic, pipeline_name);
1580 table_id >= p->n_tables ||
1581 match_check(match, p, table_id))
1584 if (!pipeline_is_running(p)) {
1585 union table_rule_match_low_level match_ll;
1588 status = match_convert(match, &match_ll, 0);
1592 status = rte_pipeline_table_entry_delete(p->p,
1601 /* Allocate request */
1602 req = pipeline_msg_alloc();
1607 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1609 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1611 /* Send request and wait for response */
1612 rsp = pipeline_msg_send_recv(p, req);
1615 status = rsp->status;
1618 pipeline_msg_free(rsp);
1624 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1625 const char *pipeline_name,
1629 struct pipeline_msg_req *req;
1630 struct pipeline_msg_rsp *rsp;
1633 /* Check input params */
1634 if (pipeline_name == NULL)
1637 p = softnic_pipeline_find(softnic, pipeline_name);
1639 table_id >= p->n_tables)
1642 if (!pipeline_is_running(p)) {
1643 status = rte_pipeline_table_default_entry_delete(p->p,
1650 /* Allocate request */
1651 req = pipeline_msg_alloc();
1656 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1659 /* Send request and wait for response */
1660 rsp = pipeline_msg_send_recv(p, req);
1663 status = rsp->status;
1666 pipeline_msg_free(rsp);
1672 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1673 const char *pipeline_name,
1676 struct rte_table_action_stats_counters *stats,
1680 struct pipeline_msg_req *req;
1681 struct pipeline_msg_rsp *rsp;
1684 /* Check input params */
1685 if (pipeline_name == NULL ||
1690 p = softnic_pipeline_find(softnic, pipeline_name);
1692 table_id >= p->n_tables)
1695 if (!pipeline_is_running(p)) {
1696 struct rte_table_action *a = p->table[table_id].a;
1698 status = rte_table_action_stats_read(a,
1706 /* Allocate request */
1707 req = pipeline_msg_alloc();
1712 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1714 req->table_rule_stats_read.data = data;
1715 req->table_rule_stats_read.clear = clear;
1717 /* Send request and wait for response */
1718 rsp = pipeline_msg_send_recv(p, req);
1721 status = rsp->status;
1723 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1726 pipeline_msg_free(rsp);
1732 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1733 const char *pipeline_name,
1735 uint32_t meter_profile_id,
1736 struct rte_table_action_meter_profile *profile)
1739 struct pipeline_msg_req *req;
1740 struct pipeline_msg_rsp *rsp;
1741 struct softnic_table *table;
1742 struct softnic_table_meter_profile *mp;
1745 /* Check input params */
1746 if (pipeline_name == NULL ||
1750 p = softnic_pipeline_find(softnic, pipeline_name);
1752 table_id >= p->n_tables)
1755 table = &p->table[table_id];
1756 mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
1760 /* Resource Allocation */
1761 mp = calloc(1, sizeof(struct softnic_table_meter_profile));
1765 mp->meter_profile_id = meter_profile_id;
1766 memcpy(&mp->profile, profile, sizeof(mp->profile));
1768 if (!pipeline_is_running(p)) {
1769 status = rte_table_action_meter_profile_add(table->a,
1777 /* Add profile to the table. */
1778 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1783 /* Allocate request */
1784 req = pipeline_msg_alloc();
1791 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1793 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1794 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1796 /* Send request and wait for response */
1797 rsp = pipeline_msg_send_recv(p, req);
1800 status = rsp->status;
1802 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1807 pipeline_msg_free(rsp);
1813 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1814 const char *pipeline_name,
1816 uint32_t meter_profile_id)
1819 struct pipeline_msg_req *req;
1820 struct pipeline_msg_rsp *rsp;
1823 /* Check input params */
1824 if (pipeline_name == NULL)
1827 p = softnic_pipeline_find(softnic, pipeline_name);
1829 table_id >= p->n_tables)
1832 if (!pipeline_is_running(p)) {
1833 struct rte_table_action *a = p->table[table_id].a;
1835 status = rte_table_action_meter_profile_delete(a,
1841 /* Allocate request */
1842 req = pipeline_msg_alloc();
1847 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1849 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1851 /* Send request and wait for response */
1852 rsp = pipeline_msg_send_recv(p, req);
1855 status = rsp->status;
1858 pipeline_msg_free(rsp);
1864 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1865 const char *pipeline_name,
1869 struct rte_table_action_mtr_counters *stats,
1873 struct pipeline_msg_req *req;
1874 struct pipeline_msg_rsp *rsp;
1877 /* Check input params */
1878 if (pipeline_name == NULL ||
1883 p = softnic_pipeline_find(softnic, pipeline_name);
1885 table_id >= p->n_tables)
1888 if (!pipeline_is_running(p)) {
1889 struct rte_table_action *a = p->table[table_id].a;
1891 status = rte_table_action_meter_read(a,
1900 /* Allocate request */
1901 req = pipeline_msg_alloc();
1906 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1908 req->table_rule_mtr_read.data = data;
1909 req->table_rule_mtr_read.tc_mask = tc_mask;
1910 req->table_rule_mtr_read.clear = clear;
1912 /* Send request and wait for response */
1913 rsp = pipeline_msg_send_recv(p, req);
1916 status = rsp->status;
1918 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1921 pipeline_msg_free(rsp);
1927 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1928 const char *pipeline_name,
1931 struct rte_table_action_dscp_table *dscp_table)
1934 struct pipeline_msg_req *req;
1935 struct pipeline_msg_rsp *rsp;
1938 /* Check input params */
1939 if (pipeline_name == NULL ||
1943 p = softnic_pipeline_find(softnic, pipeline_name);
1945 table_id >= p->n_tables)
1948 if (!pipeline_is_running(p)) {
1949 struct rte_table_action *a = p->table[table_id].a;
1951 status = rte_table_action_dscp_table_update(a,
1955 /* Update table dscp table */
1957 memcpy(&p->table[table_id].dscp_table, dscp_table,
1958 sizeof(p->table[table_id].dscp_table));
1963 /* Allocate request */
1964 req = pipeline_msg_alloc();
1969 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
1971 req->table_dscp_table_update.dscp_mask = dscp_mask;
1972 memcpy(&req->table_dscp_table_update.dscp_table,
1973 dscp_table, sizeof(*dscp_table));
1975 /* Send request and wait for response */
1976 rsp = pipeline_msg_send_recv(p, req);
1979 status = rsp->status;
1981 /* Update table dscp table */
1983 memcpy(&p->table[table_id].dscp_table, dscp_table,
1984 sizeof(p->table[table_id].dscp_table));
1987 pipeline_msg_free(rsp);
1993 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
1994 const char *pipeline_name,
1997 struct rte_table_action_ttl_counters *stats,
2001 struct pipeline_msg_req *req;
2002 struct pipeline_msg_rsp *rsp;
2005 /* Check input params */
2006 if (pipeline_name == NULL ||
2011 p = softnic_pipeline_find(softnic, pipeline_name);
2013 table_id >= p->n_tables)
2016 if (!pipeline_is_running(p)) {
2017 struct rte_table_action *a = p->table[table_id].a;
2019 status = rte_table_action_ttl_read(a,
2027 /* Allocate request */
2028 req = pipeline_msg_alloc();
2033 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
2035 req->table_rule_ttl_read.data = data;
2036 req->table_rule_ttl_read.clear = clear;
2038 /* Send request and wait for response */
2039 rsp = pipeline_msg_send_recv(p, req);
2042 status = rsp->status;
2044 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2047 pipeline_msg_free(rsp);
2053 * Data plane threads: message handling
2055 static inline struct pipeline_msg_req *
2056 pipeline_msg_recv(struct rte_ring *msgq_req)
2058 struct pipeline_msg_req *req;
2060 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2069 pipeline_msg_send(struct rte_ring *msgq_rsp,
2070 struct pipeline_msg_rsp *rsp)
2075 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2076 } while (status == -ENOBUFS);
2079 static struct pipeline_msg_rsp *
2080 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2081 struct pipeline_msg_req *req)
2083 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2084 uint32_t port_id = req->id;
2085 int clear = req->port_in_stats_read.clear;
2087 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2089 &rsp->port_in_stats_read.stats,
2095 static struct pipeline_msg_rsp *
2096 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2097 struct pipeline_msg_req *req)
2099 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2100 uint32_t port_id = req->id;
2102 rsp->status = rte_pipeline_port_in_enable(p->p,
2108 static struct pipeline_msg_rsp *
2109 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2110 struct pipeline_msg_req *req)
2112 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2113 uint32_t port_id = req->id;
2115 rsp->status = rte_pipeline_port_in_disable(p->p,
2121 static struct pipeline_msg_rsp *
2122 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2123 struct pipeline_msg_req *req)
2125 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2126 uint32_t port_id = req->id;
2127 int clear = req->port_out_stats_read.clear;
2129 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2131 &rsp->port_out_stats_read.stats,
2137 static struct pipeline_msg_rsp *
2138 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2139 struct pipeline_msg_req *req)
2141 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2142 uint32_t port_id = req->id;
2143 int clear = req->table_stats_read.clear;
2145 rsp->status = rte_pipeline_table_stats_read(p->p,
2147 &rsp->table_stats_read.stats,
2154 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2159 switch (depth / 32) {
2169 depth32[1] = depth - 32;
2177 depth32[2] = depth - 64;
2185 depth32[3] = depth - 96;
2201 match_convert(struct softnic_table_rule_match *mh,
2202 union table_rule_match_low_level *ml,
2205 memset(ml, 0, sizeof(*ml));
2207 switch (mh->match_type) {
2209 if (mh->match.acl.ip_version)
2211 ml->acl_add.field_value[0].value.u8 =
2212 mh->match.acl.proto;
2213 ml->acl_add.field_value[0].mask_range.u8 =
2214 mh->match.acl.proto_mask;
2216 ml->acl_add.field_value[1].value.u32 =
2217 mh->match.acl.ipv4.sa;
2218 ml->acl_add.field_value[1].mask_range.u32 =
2219 mh->match.acl.sa_depth;
2221 ml->acl_add.field_value[2].value.u32 =
2222 mh->match.acl.ipv4.da;
2223 ml->acl_add.field_value[2].mask_range.u32 =
2224 mh->match.acl.da_depth;
2226 ml->acl_add.field_value[3].value.u16 =
2228 ml->acl_add.field_value[3].mask_range.u16 =
2231 ml->acl_add.field_value[4].value.u16 =
2233 ml->acl_add.field_value[4].mask_range.u16 =
2236 ml->acl_add.priority =
2237 (int32_t)mh->match.acl.priority;
2239 ml->acl_delete.field_value[0].value.u8 =
2240 mh->match.acl.proto;
2241 ml->acl_delete.field_value[0].mask_range.u8 =
2242 mh->match.acl.proto_mask;
2244 ml->acl_delete.field_value[1].value.u32 =
2245 mh->match.acl.ipv4.sa;
2246 ml->acl_delete.field_value[1].mask_range.u32 =
2247 mh->match.acl.sa_depth;
2249 ml->acl_delete.field_value[2].value.u32 =
2250 mh->match.acl.ipv4.da;
2251 ml->acl_delete.field_value[2].mask_range.u32 =
2252 mh->match.acl.da_depth;
2254 ml->acl_delete.field_value[3].value.u16 =
2256 ml->acl_delete.field_value[3].mask_range.u16 =
2259 ml->acl_delete.field_value[4].value.u16 =
2261 ml->acl_delete.field_value[4].mask_range.u16 =
2267 (uint32_t *)mh->match.acl.ipv6.sa;
2269 (uint32_t *)mh->match.acl.ipv6.da;
2270 uint32_t sa32_depth[4], da32_depth[4];
2273 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2278 status = match_convert_ipv6_depth(
2279 mh->match.acl.da_depth,
2284 ml->acl_add.field_value[0].value.u8 =
2285 mh->match.acl.proto;
2286 ml->acl_add.field_value[0].mask_range.u8 =
2287 mh->match.acl.proto_mask;
2289 ml->acl_add.field_value[1].value.u32 =
2290 rte_be_to_cpu_32(sa32[0]);
2291 ml->acl_add.field_value[1].mask_range.u32 =
2293 ml->acl_add.field_value[2].value.u32 =
2294 rte_be_to_cpu_32(sa32[1]);
2295 ml->acl_add.field_value[2].mask_range.u32 =
2297 ml->acl_add.field_value[3].value.u32 =
2298 rte_be_to_cpu_32(sa32[2]);
2299 ml->acl_add.field_value[3].mask_range.u32 =
2301 ml->acl_add.field_value[4].value.u32 =
2302 rte_be_to_cpu_32(sa32[3]);
2303 ml->acl_add.field_value[4].mask_range.u32 =
2306 ml->acl_add.field_value[5].value.u32 =
2307 rte_be_to_cpu_32(da32[0]);
2308 ml->acl_add.field_value[5].mask_range.u32 =
2310 ml->acl_add.field_value[6].value.u32 =
2311 rte_be_to_cpu_32(da32[1]);
2312 ml->acl_add.field_value[6].mask_range.u32 =
2314 ml->acl_add.field_value[7].value.u32 =
2315 rte_be_to_cpu_32(da32[2]);
2316 ml->acl_add.field_value[7].mask_range.u32 =
2318 ml->acl_add.field_value[8].value.u32 =
2319 rte_be_to_cpu_32(da32[3]);
2320 ml->acl_add.field_value[8].mask_range.u32 =
2323 ml->acl_add.field_value[9].value.u16 =
2325 ml->acl_add.field_value[9].mask_range.u16 =
2328 ml->acl_add.field_value[10].value.u16 =
2330 ml->acl_add.field_value[10].mask_range.u16 =
2333 ml->acl_add.priority =
2334 (int32_t)mh->match.acl.priority;
2337 (uint32_t *)mh->match.acl.ipv6.sa;
2339 (uint32_t *)mh->match.acl.ipv6.da;
2340 uint32_t sa32_depth[4], da32_depth[4];
2343 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2348 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2353 ml->acl_delete.field_value[0].value.u8 =
2354 mh->match.acl.proto;
2355 ml->acl_delete.field_value[0].mask_range.u8 =
2356 mh->match.acl.proto_mask;
2358 ml->acl_delete.field_value[1].value.u32 =
2359 rte_be_to_cpu_32(sa32[0]);
2360 ml->acl_delete.field_value[1].mask_range.u32 =
2362 ml->acl_delete.field_value[2].value.u32 =
2363 rte_be_to_cpu_32(sa32[1]);
2364 ml->acl_delete.field_value[2].mask_range.u32 =
2366 ml->acl_delete.field_value[3].value.u32 =
2367 rte_be_to_cpu_32(sa32[2]);
2368 ml->acl_delete.field_value[3].mask_range.u32 =
2370 ml->acl_delete.field_value[4].value.u32 =
2371 rte_be_to_cpu_32(sa32[3]);
2372 ml->acl_delete.field_value[4].mask_range.u32 =
2375 ml->acl_delete.field_value[5].value.u32 =
2376 rte_be_to_cpu_32(da32[0]);
2377 ml->acl_delete.field_value[5].mask_range.u32 =
2379 ml->acl_delete.field_value[6].value.u32 =
2380 rte_be_to_cpu_32(da32[1]);
2381 ml->acl_delete.field_value[6].mask_range.u32 =
2383 ml->acl_delete.field_value[7].value.u32 =
2384 rte_be_to_cpu_32(da32[2]);
2385 ml->acl_delete.field_value[7].mask_range.u32 =
2387 ml->acl_delete.field_value[8].value.u32 =
2388 rte_be_to_cpu_32(da32[3]);
2389 ml->acl_delete.field_value[8].mask_range.u32 =
2392 ml->acl_delete.field_value[9].value.u16 =
2394 ml->acl_delete.field_value[9].mask_range.u16 =
2397 ml->acl_delete.field_value[10].value.u16 =
2399 ml->acl_delete.field_value[10].mask_range.u16 =
2405 ml->array.pos = mh->match.array.pos;
2409 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2413 if (mh->match.lpm.ip_version) {
2414 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2415 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2417 memcpy(ml->lpm_ipv6.ip,
2418 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2419 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2430 action_convert(struct rte_table_action *a,
2431 struct softnic_table_rule_action *action,
2432 struct rte_pipeline_table_entry *data)
2437 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2438 status = rte_table_action_apply(a,
2440 RTE_TABLE_ACTION_FWD,
2447 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2448 status = rte_table_action_apply(a,
2450 RTE_TABLE_ACTION_LB,
2457 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2458 status = rte_table_action_apply(a,
2460 RTE_TABLE_ACTION_MTR,
2467 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2468 status = rte_table_action_apply(a,
2470 RTE_TABLE_ACTION_TM,
2477 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2478 status = rte_table_action_apply(a,
2480 RTE_TABLE_ACTION_ENCAP,
2487 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2488 status = rte_table_action_apply(a,
2490 RTE_TABLE_ACTION_NAT,
2497 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2498 status = rte_table_action_apply(a,
2500 RTE_TABLE_ACTION_TTL,
2507 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2508 status = rte_table_action_apply(a,
2510 RTE_TABLE_ACTION_STATS,
2517 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2518 status = rte_table_action_apply(a,
2520 RTE_TABLE_ACTION_TIME,
2527 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2528 status = rte_table_action_apply(a,
2530 RTE_TABLE_ACTION_TAG,
2537 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2538 status = rte_table_action_apply(a,
2540 RTE_TABLE_ACTION_DECAP,
2547 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2548 status = rte_table_action_apply(a,
2550 RTE_TABLE_ACTION_SYM_CRYPTO,
2551 &action->sym_crypto);
2560 static struct pipeline_msg_rsp *
2561 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2562 struct pipeline_msg_req *req)
2564 union table_rule_match_low_level match_ll;
2565 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2566 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2567 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2568 struct rte_pipeline_table_entry *data_in, *data_out;
2569 uint32_t table_id = req->id;
2570 int key_found, status;
2571 struct rte_table_action *a = p->table_data[table_id].a;
2574 memset(p->buffer, 0, sizeof(p->buffer));
2575 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2577 status = match_convert(match, &match_ll, 1);
2583 status = action_convert(a, action, data_in);
2589 status = rte_pipeline_table_entry_add(p->p,
2600 /* Write response */
2602 rsp->table_rule_add.data = data_out;
2607 static struct pipeline_msg_rsp *
2608 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2609 struct pipeline_msg_req *req)
2611 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2612 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2613 struct rte_pipeline_table_entry *data_in, *data_out;
2614 uint32_t table_id = req->id;
2618 memset(p->buffer, 0, sizeof(p->buffer));
2619 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2621 data_in->action = action->fwd.action;
2622 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2623 data_in->port_id = action->fwd.id;
2624 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2625 data_in->table_id = action->fwd.id;
2627 /* Add default rule to table */
2628 status = rte_pipeline_table_default_entry_add(p->p,
2637 /* Write response */
2639 rsp->table_rule_add_default.data = data_out;
2644 static struct pipeline_msg_rsp *
2645 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2646 struct pipeline_msg_req *req)
2648 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2650 uint32_t table_id = req->id;
2651 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2652 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2653 struct rte_pipeline_table_entry **data =
2654 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2655 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2656 uint32_t bulk = req->table_rule_add_bulk.bulk;
2658 struct rte_table_action *a = p->table_data[table_id].a;
2659 union table_rule_match_low_level *match_ll;
2661 void **match_ll_ptr;
2662 struct rte_pipeline_table_entry **action_ll_ptr;
2666 /* Memory allocation */
2667 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2668 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2669 match_ll_ptr = calloc(n_rules, sizeof(void *));
2671 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2672 found = calloc(n_rules, sizeof(int));
2674 if (match_ll == NULL ||
2675 action_ll == NULL ||
2676 match_ll_ptr == NULL ||
2677 action_ll_ptr == NULL ||
2681 for (i = 0; i < n_rules; i++) {
2682 match_ll_ptr[i] = (void *)&match_ll[i];
2684 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2687 /* Rule match conversion */
2688 for (i = 0; i < n_rules; i++) {
2689 status = match_convert(&match[i], match_ll_ptr[i], 1);
2694 /* Rule action conversion */
2695 for (i = 0; i < n_rules; i++) {
2696 status = action_convert(a, &action[i], action_ll_ptr[i]);
2701 /* Add rule (match, action) to table */
2703 status = rte_pipeline_table_entry_add_bulk(p->p,
2713 for (i = 0; i < n_rules; i++) {
2714 status = rte_pipeline_table_entry_add(p->p,
2727 /* Write response */
2729 rsp->table_rule_add_bulk.n_rules = n_rules;
2733 free(action_ll_ptr);
2742 free(action_ll_ptr);
2748 rsp->table_rule_add_bulk.n_rules = 0;
2752 static struct pipeline_msg_rsp *
2753 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2754 struct pipeline_msg_req *req)
2756 union table_rule_match_low_level match_ll;
2757 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2758 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2759 uint32_t table_id = req->id;
2760 int key_found, status;
2762 status = match_convert(match, &match_ll, 0);
2768 rsp->status = rte_pipeline_table_entry_delete(p->p,
2777 static struct pipeline_msg_rsp *
2778 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2779 struct pipeline_msg_req *req)
2781 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2782 uint32_t table_id = req->id;
2784 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2791 static struct pipeline_msg_rsp *
2792 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2793 struct pipeline_msg_req *req)
2795 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2796 uint32_t table_id = req->id;
2797 void *data = req->table_rule_stats_read.data;
2798 int clear = req->table_rule_stats_read.clear;
2799 struct rte_table_action *a = p->table_data[table_id].a;
2801 rsp->status = rte_table_action_stats_read(a,
2803 &rsp->table_rule_stats_read.stats,
2809 static struct pipeline_msg_rsp *
2810 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2811 struct pipeline_msg_req *req)
2813 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2814 uint32_t table_id = req->id;
2815 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2816 struct rte_table_action_meter_profile *profile =
2817 &req->table_mtr_profile_add.profile;
2818 struct rte_table_action *a = p->table_data[table_id].a;
2820 rsp->status = rte_table_action_meter_profile_add(a,
2827 static struct pipeline_msg_rsp *
2828 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2829 struct pipeline_msg_req *req)
2831 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2832 uint32_t table_id = req->id;
2833 uint32_t meter_profile_id =
2834 req->table_mtr_profile_delete.meter_profile_id;
2835 struct rte_table_action *a = p->table_data[table_id].a;
2837 rsp->status = rte_table_action_meter_profile_delete(a,
2843 static struct pipeline_msg_rsp *
2844 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2845 struct pipeline_msg_req *req)
2847 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2848 uint32_t table_id = req->id;
2849 void *data = req->table_rule_mtr_read.data;
2850 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2851 int clear = req->table_rule_mtr_read.clear;
2852 struct rte_table_action *a = p->table_data[table_id].a;
2854 rsp->status = rte_table_action_meter_read(a,
2857 &rsp->table_rule_mtr_read.stats,
2863 static struct pipeline_msg_rsp *
2864 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2865 struct pipeline_msg_req *req)
2867 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2868 uint32_t table_id = req->id;
2869 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2870 struct rte_table_action_dscp_table *dscp_table =
2871 &req->table_dscp_table_update.dscp_table;
2872 struct rte_table_action *a = p->table_data[table_id].a;
2874 rsp->status = rte_table_action_dscp_table_update(a,
2881 static struct pipeline_msg_rsp *
2882 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2883 struct pipeline_msg_req *req)
2885 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2886 uint32_t table_id = req->id;
2887 void *data = req->table_rule_ttl_read.data;
2888 int clear = req->table_rule_ttl_read.clear;
2889 struct rte_table_action *a = p->table_data[table_id].a;
2891 rsp->status = rte_table_action_ttl_read(a,
2893 &rsp->table_rule_ttl_read.stats,
2900 pipeline_msg_handle(struct pipeline_data *p)
2903 struct pipeline_msg_req *req;
2904 struct pipeline_msg_rsp *rsp;
2906 req = pipeline_msg_recv(p->msgq_req);
2910 switch (req->type) {
2911 case PIPELINE_REQ_PORT_IN_STATS_READ:
2912 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2915 case PIPELINE_REQ_PORT_IN_ENABLE:
2916 rsp = pipeline_msg_handle_port_in_enable(p, req);
2919 case PIPELINE_REQ_PORT_IN_DISABLE:
2920 rsp = pipeline_msg_handle_port_in_disable(p, req);
2923 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2924 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2927 case PIPELINE_REQ_TABLE_STATS_READ:
2928 rsp = pipeline_msg_handle_table_stats_read(p, req);
2931 case PIPELINE_REQ_TABLE_RULE_ADD:
2932 rsp = pipeline_msg_handle_table_rule_add(p, req);
2935 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2936 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2939 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2940 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2943 case PIPELINE_REQ_TABLE_RULE_DELETE:
2944 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2947 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2948 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2951 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2952 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2955 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2956 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
2959 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
2960 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
2963 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
2964 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
2967 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
2968 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
2971 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
2972 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
2976 rsp = (struct pipeline_msg_rsp *)req;
2980 pipeline_msg_send(p->msgq_rsp, rsp);
2985 * Data plane threads: main
2988 rte_pmd_softnic_run_internal(void *arg)
2990 struct rte_eth_dev *dev = arg;
2991 struct pmd_internals *softnic;
2992 struct softnic_thread_data *t;
2993 uint32_t thread_id, j;
2995 softnic = dev->data->dev_private;
2996 thread_id = rte_lcore_id();
2997 t = &softnic->thread_data[thread_id];
3001 for (j = 0; j < t->n_pipelines; j++)
3002 rte_pipeline_run(t->p[j]);
3005 if ((t->iter & 0xFLLU) == 0) {
3006 uint64_t time = rte_get_tsc_cycles();
3007 uint64_t time_next_min = UINT64_MAX;
3009 if (time < t->time_next_min)
3012 /* Pipeline message queues */
3013 for (j = 0; j < t->n_pipelines; j++) {
3014 struct pipeline_data *p =
3015 &t->pipeline_data[j];
3016 uint64_t time_next = p->time_next;
3018 if (time_next <= time) {
3019 pipeline_msg_handle(p);
3020 rte_pipeline_flush(p->p);
3021 time_next = time + p->timer_period;
3022 p->time_next = time_next;
3025 if (time_next < time_next_min)
3026 time_next_min = time_next;
3029 /* Thread message queues */
3031 uint64_t time_next = t->time_next;
3033 if (time_next <= time) {
3034 thread_msg_handle(t);
3035 time_next = time + t->timer_period;
3036 t->time_next = time_next;
3039 if (time_next < time_next_min)
3040 time_next_min = time_next;
3043 t->time_next_min = time_next_min;
3050 rte_pmd_softnic_run(uint16_t port_id)
3052 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3054 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
3055 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
3058 return (int)rte_pmd_softnic_run_internal(dev);