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 * Master thread: data plane thread init
24 softnic_thread_free(struct pmd_internals *softnic)
28 RTE_LCORE_FOREACH_SLAVE(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 /* Master 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 struct rte_config *cfg = rte_eal_get_configuration();
103 enum rte_lcore_role_t role;
105 if ((thread_id >= RTE_MAX_LCORE) ||
106 (thread_id == cfg->master_lcore))
107 return 0; /* FALSE */
109 role = cfg->lcore_role[thread_id];
111 if ((softnic->params.sc && (role == ROLE_SERVICE)) ||
112 (!softnic->params.sc && (role == ROLE_RTE)))
115 return 0; /* FALSE */
119 thread_is_running(uint32_t thread_id)
121 enum rte_lcore_state_t thread_state;
123 thread_state = rte_eal_get_lcore_state(thread_id);
124 return (thread_state == RUNNING)? 1 : 0;
128 rte_pmd_softnic_run_internal(void *arg);
131 thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
133 struct rte_service_spec service_params;
134 struct softnic_thread *t = &softnic->thread[thread_id];
135 struct rte_eth_dev *dev;
140 rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
141 dev = &rte_eth_devices[port_id];
142 snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
143 softnic->params.name,
145 service_params.callback = rte_pmd_softnic_run_internal;
146 service_params.callback_userdata = dev;
147 service_params.capabilities = 0;
148 service_params.socket_id = (int)softnic->params.cpu_id;
150 /* service register */
151 status = rte_service_component_register(&service_params, &t->service_id);
155 status = rte_service_component_runstate_set(t->service_id, 1);
157 rte_service_component_unregister(t->service_id);
158 t->service_id = UINT32_MAX;
162 status = rte_service_runstate_set(t->service_id, 1);
164 rte_service_component_runstate_set(t->service_id, 0);
165 rte_service_component_unregister(t->service_id);
166 t->service_id = UINT32_MAX;
170 /* service map to thread */
171 status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
173 rte_service_runstate_set(t->service_id, 0);
174 rte_service_component_runstate_set(t->service_id, 0);
175 rte_service_component_unregister(t->service_id);
176 t->service_id = UINT32_MAX;
184 thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
186 struct softnic_thread *t = &softnic->thread[thread_id];
188 /* service unmap from thread */
189 rte_service_map_lcore_set(t->service_id, thread_id, 0);
191 /* service unregister */
192 rte_service_runstate_set(t->service_id, 0);
193 rte_service_component_runstate_set(t->service_id, 0);
194 rte_service_component_unregister(t->service_id);
196 t->service_id = UINT32_MAX;
200 * Pipeline is running when:
201 * (A) Pipeline is mapped to a data plane thread AND
202 * (B) Its data plane thread is in RUNNING state.
205 pipeline_is_running(struct pipeline *p)
210 return thread_is_running(p->thread_id);
214 * Master thread & data plane threads: message passing
216 enum thread_req_type {
217 THREAD_REQ_PIPELINE_ENABLE = 0,
218 THREAD_REQ_PIPELINE_DISABLE,
222 struct thread_msg_req {
223 enum thread_req_type type;
227 struct rte_pipeline *p;
229 struct rte_table_action *a;
230 } table[RTE_PIPELINE_TABLE_MAX];
231 struct rte_ring *msgq_req;
232 struct rte_ring *msgq_rsp;
233 uint32_t timer_period_ms;
238 struct rte_pipeline *p;
243 struct thread_msg_rsp {
250 static struct thread_msg_req *
251 thread_msg_alloc(void)
253 size_t size = RTE_MAX(sizeof(struct thread_msg_req),
254 sizeof(struct thread_msg_rsp));
256 return calloc(1, size);
260 thread_msg_free(struct thread_msg_rsp *rsp)
265 static struct thread_msg_rsp *
266 thread_msg_send_recv(struct pmd_internals *softnic,
268 struct thread_msg_req *req)
270 struct softnic_thread *t = &softnic->thread[thread_id];
271 struct rte_ring *msgq_req = t->msgq_req;
272 struct rte_ring *msgq_rsp = t->msgq_rsp;
273 struct thread_msg_rsp *rsp;
278 status = rte_ring_sp_enqueue(msgq_req, req);
279 } while (status == -ENOBUFS);
283 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
284 } while (status != 0);
290 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
292 const char *pipeline_name)
294 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
295 struct thread_msg_req *req;
296 struct thread_msg_rsp *rsp;
297 uint32_t n_pipelines, i;
300 /* Check input params */
301 if (!thread_is_valid(softnic, thread_id) ||
303 (p->n_ports_in == 0) ||
304 (p->n_ports_out == 0) ||
305 (p->n_tables == 0) ||
309 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
310 if (n_pipelines >= THREAD_PIPELINES_MAX)
313 if (softnic->params.sc && (n_pipelines == 0)) {
314 status = thread_sc_service_up(softnic, thread_id);
319 if (!thread_is_running(thread_id)) {
320 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
321 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
323 /* Data plane thread */
324 td->p[td->n_pipelines] = p->p;
327 for (i = 0; i < p->n_tables; i++)
328 tdp->table_data[i].a =
330 tdp->n_tables = p->n_tables;
332 tdp->msgq_req = p->msgq_req;
333 tdp->msgq_rsp = p->msgq_rsp;
334 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
335 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
340 p->thread_id = thread_id;
346 /* Allocate request */
347 req = thread_msg_alloc();
352 req->type = THREAD_REQ_PIPELINE_ENABLE;
353 req->pipeline_enable.p = p->p;
354 for (i = 0; i < p->n_tables; i++)
355 req->pipeline_enable.table[i].a =
357 req->pipeline_enable.msgq_req = p->msgq_req;
358 req->pipeline_enable.msgq_rsp = p->msgq_rsp;
359 req->pipeline_enable.timer_period_ms = p->timer_period_ms;
360 req->pipeline_enable.n_tables = p->n_tables;
362 /* Send request and wait for response */
363 rsp = thread_msg_send_recv(softnic, thread_id, req);
368 status = rsp->status;
371 thread_msg_free(rsp);
373 /* Request completion */
377 p->thread_id = thread_id;
384 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
386 const char *pipeline_name)
388 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
389 struct thread_msg_req *req;
390 struct thread_msg_rsp *rsp;
391 uint32_t n_pipelines;
394 /* Check input params */
395 if (!thread_is_valid(softnic, thread_id) ||
397 (p->enabled && (p->thread_id != thread_id)))
403 if (!thread_is_running(thread_id)) {
404 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
407 for (i = 0; i < td->n_pipelines; i++) {
408 struct pipeline_data *tdp = &td->pipeline_data[i];
413 /* Data plane thread */
414 if (i < td->n_pipelines - 1) {
415 struct rte_pipeline *pipeline_last =
416 td->p[td->n_pipelines - 1];
417 struct pipeline_data *tdp_last =
418 &td->pipeline_data[td->n_pipelines - 1];
420 td->p[i] = pipeline_last;
421 memcpy(tdp, tdp_last, sizeof(*tdp));
432 if (softnic->params.sc && (td->n_pipelines == 0))
433 thread_sc_service_down(softnic, thread_id);
438 /* Allocate request */
439 req = thread_msg_alloc();
444 req->type = THREAD_REQ_PIPELINE_DISABLE;
445 req->pipeline_disable.p = p->p;
447 /* Send request and wait for response */
448 rsp = thread_msg_send_recv(softnic, thread_id, req);
453 status = rsp->status;
456 thread_msg_free(rsp);
458 /* Request completion */
464 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
465 if (softnic->params.sc && (n_pipelines == 0))
466 thread_sc_service_down(softnic, thread_id);
472 * Data plane threads: message handling
474 static inline struct thread_msg_req *
475 thread_msg_recv(struct rte_ring *msgq_req)
477 struct thread_msg_req *req;
479 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
488 thread_msg_send(struct rte_ring *msgq_rsp,
489 struct thread_msg_rsp *rsp)
494 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
495 } while (status == -ENOBUFS);
498 static struct thread_msg_rsp *
499 thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
500 struct thread_msg_req *req)
502 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
503 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
507 t->p[t->n_pipelines] = req->pipeline_enable.p;
509 p->p = req->pipeline_enable.p;
510 for (i = 0; i < req->pipeline_enable.n_tables; i++)
512 req->pipeline_enable.table[i].a;
514 p->n_tables = req->pipeline_enable.n_tables;
516 p->msgq_req = req->pipeline_enable.msgq_req;
517 p->msgq_rsp = req->pipeline_enable.msgq_rsp;
519 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
520 p->time_next = rte_get_tsc_cycles() + p->timer_period;
529 static struct thread_msg_rsp *
530 thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
531 struct thread_msg_req *req)
533 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
534 uint32_t n_pipelines = t->n_pipelines;
535 struct rte_pipeline *pipeline = req->pipeline_disable.p;
539 for (i = 0; i < n_pipelines; i++) {
540 struct pipeline_data *p = &t->pipeline_data[i];
542 if (p->p != pipeline)
545 if (i < n_pipelines - 1) {
546 struct rte_pipeline *pipeline_last =
547 t->p[n_pipelines - 1];
548 struct pipeline_data *p_last =
549 &t->pipeline_data[n_pipelines - 1];
551 t->p[i] = pipeline_last;
552 memcpy(p, p_last, sizeof(*p));
561 /* should not get here */
567 thread_msg_handle(struct softnic_thread_data *t)
570 struct thread_msg_req *req;
571 struct thread_msg_rsp *rsp;
573 req = thread_msg_recv(t->msgq_req);
578 case THREAD_REQ_PIPELINE_ENABLE:
579 rsp = thread_msg_handle_pipeline_enable(t, req);
582 case THREAD_REQ_PIPELINE_DISABLE:
583 rsp = thread_msg_handle_pipeline_disable(t, req);
587 rsp = (struct thread_msg_rsp *)req;
591 thread_msg_send(t->msgq_rsp, rsp);
596 * Master thread & data plane threads: message passing
598 enum pipeline_req_type {
600 PIPELINE_REQ_PORT_IN_STATS_READ,
601 PIPELINE_REQ_PORT_IN_ENABLE,
602 PIPELINE_REQ_PORT_IN_DISABLE,
605 PIPELINE_REQ_PORT_OUT_STATS_READ,
608 PIPELINE_REQ_TABLE_STATS_READ,
609 PIPELINE_REQ_TABLE_RULE_ADD,
610 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
611 PIPELINE_REQ_TABLE_RULE_ADD_BULK,
612 PIPELINE_REQ_TABLE_RULE_DELETE,
613 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
614 PIPELINE_REQ_TABLE_RULE_STATS_READ,
615 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
616 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
617 PIPELINE_REQ_TABLE_RULE_MTR_READ,
618 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
619 PIPELINE_REQ_TABLE_RULE_TTL_READ,
623 struct pipeline_msg_req_port_in_stats_read {
627 struct pipeline_msg_req_port_out_stats_read {
631 struct pipeline_msg_req_table_stats_read {
635 struct pipeline_msg_req_table_rule_add {
636 struct softnic_table_rule_match match;
637 struct softnic_table_rule_action action;
640 struct pipeline_msg_req_table_rule_add_default {
641 struct softnic_table_rule_action action;
644 struct pipeline_msg_req_table_rule_add_bulk {
645 struct softnic_table_rule_match *match;
646 struct softnic_table_rule_action *action;
652 struct pipeline_msg_req_table_rule_delete {
653 struct softnic_table_rule_match match;
656 struct pipeline_msg_req_table_rule_stats_read {
661 struct pipeline_msg_req_table_mtr_profile_add {
662 uint32_t meter_profile_id;
663 struct rte_table_action_meter_profile profile;
666 struct pipeline_msg_req_table_mtr_profile_delete {
667 uint32_t meter_profile_id;
670 struct pipeline_msg_req_table_rule_mtr_read {
676 struct pipeline_msg_req_table_dscp_table_update {
678 struct rte_table_action_dscp_table dscp_table;
681 struct pipeline_msg_req_table_rule_ttl_read {
686 struct pipeline_msg_req {
687 enum pipeline_req_type type;
688 uint32_t id; /* Port IN, port OUT or table ID */
692 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
693 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
694 struct pipeline_msg_req_table_stats_read table_stats_read;
695 struct pipeline_msg_req_table_rule_add table_rule_add;
696 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
697 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
698 struct pipeline_msg_req_table_rule_delete table_rule_delete;
699 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
700 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
701 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
702 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
703 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
704 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
708 struct pipeline_msg_rsp_port_in_stats_read {
709 struct rte_pipeline_port_in_stats stats;
712 struct pipeline_msg_rsp_port_out_stats_read {
713 struct rte_pipeline_port_out_stats stats;
716 struct pipeline_msg_rsp_table_stats_read {
717 struct rte_pipeline_table_stats stats;
720 struct pipeline_msg_rsp_table_rule_add {
724 struct pipeline_msg_rsp_table_rule_add_default {
728 struct pipeline_msg_rsp_table_rule_add_bulk {
732 struct pipeline_msg_rsp_table_rule_stats_read {
733 struct rte_table_action_stats_counters stats;
736 struct pipeline_msg_rsp_table_rule_mtr_read {
737 struct rte_table_action_mtr_counters stats;
740 struct pipeline_msg_rsp_table_rule_ttl_read {
741 struct rte_table_action_ttl_counters stats;
744 struct pipeline_msg_rsp {
749 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
750 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
751 struct pipeline_msg_rsp_table_stats_read table_stats_read;
752 struct pipeline_msg_rsp_table_rule_add table_rule_add;
753 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
754 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
755 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
756 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
757 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
764 static struct pipeline_msg_req *
765 pipeline_msg_alloc(void)
767 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
768 sizeof(struct pipeline_msg_rsp));
770 return calloc(1, size);
774 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
779 static struct pipeline_msg_rsp *
780 pipeline_msg_send_recv(struct pipeline *p,
781 struct pipeline_msg_req *req)
783 struct rte_ring *msgq_req = p->msgq_req;
784 struct rte_ring *msgq_rsp = p->msgq_rsp;
785 struct pipeline_msg_rsp *rsp;
790 status = rte_ring_sp_enqueue(msgq_req, req);
791 } while (status == -ENOBUFS);
795 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
796 } while (status != 0);
802 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
803 const char *pipeline_name,
805 struct rte_pipeline_port_in_stats *stats,
809 struct pipeline_msg_req *req;
810 struct pipeline_msg_rsp *rsp;
813 /* Check input params */
814 if (pipeline_name == NULL ||
818 p = softnic_pipeline_find(softnic, pipeline_name);
820 port_id >= p->n_ports_in)
823 if (!pipeline_is_running(p)) {
824 status = rte_pipeline_port_in_stats_read(p->p,
832 /* Allocate request */
833 req = pipeline_msg_alloc();
838 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
840 req->port_in_stats_read.clear = clear;
842 /* Send request and wait for response */
843 rsp = pipeline_msg_send_recv(p, req);
848 status = rsp->status;
850 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
853 pipeline_msg_free(rsp);
859 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
860 const char *pipeline_name,
864 struct pipeline_msg_req *req;
865 struct pipeline_msg_rsp *rsp;
868 /* Check input params */
869 if (pipeline_name == NULL)
872 p = softnic_pipeline_find(softnic, pipeline_name);
874 port_id >= p->n_ports_in)
877 if (!pipeline_is_running(p)) {
878 status = rte_pipeline_port_in_enable(p->p, port_id);
882 /* Allocate request */
883 req = pipeline_msg_alloc();
888 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
891 /* Send request and wait for response */
892 rsp = pipeline_msg_send_recv(p, req);
897 status = rsp->status;
900 pipeline_msg_free(rsp);
906 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
907 const char *pipeline_name,
911 struct pipeline_msg_req *req;
912 struct pipeline_msg_rsp *rsp;
915 /* Check input params */
916 if (pipeline_name == NULL)
919 p = softnic_pipeline_find(softnic, pipeline_name);
921 port_id >= p->n_ports_in)
924 if (!pipeline_is_running(p)) {
925 status = rte_pipeline_port_in_disable(p->p, port_id);
929 /* Allocate request */
930 req = pipeline_msg_alloc();
935 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
938 /* Send request and wait for response */
939 rsp = pipeline_msg_send_recv(p, req);
944 status = rsp->status;
947 pipeline_msg_free(rsp);
953 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
954 const char *pipeline_name,
956 struct rte_pipeline_port_out_stats *stats,
960 struct pipeline_msg_req *req;
961 struct pipeline_msg_rsp *rsp;
964 /* Check input params */
965 if (pipeline_name == NULL ||
969 p = softnic_pipeline_find(softnic, pipeline_name);
971 port_id >= p->n_ports_out)
974 if (!pipeline_is_running(p)) {
975 status = rte_pipeline_port_out_stats_read(p->p,
983 /* Allocate request */
984 req = pipeline_msg_alloc();
989 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
991 req->port_out_stats_read.clear = clear;
993 /* Send request and wait for response */
994 rsp = pipeline_msg_send_recv(p, req);
999 status = rsp->status;
1001 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
1004 pipeline_msg_free(rsp);
1010 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
1011 const char *pipeline_name,
1013 struct rte_pipeline_table_stats *stats,
1017 struct pipeline_msg_req *req;
1018 struct pipeline_msg_rsp *rsp;
1021 /* Check input params */
1022 if (pipeline_name == NULL ||
1026 p = softnic_pipeline_find(softnic, pipeline_name);
1028 table_id >= p->n_tables)
1031 if (!pipeline_is_running(p)) {
1032 status = rte_pipeline_table_stats_read(p->p,
1040 /* Allocate request */
1041 req = pipeline_msg_alloc();
1046 req->type = PIPELINE_REQ_TABLE_STATS_READ;
1048 req->table_stats_read.clear = clear;
1050 /* Send request and wait for response */
1051 rsp = pipeline_msg_send_recv(p, req);
1056 status = rsp->status;
1058 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
1061 pipeline_msg_free(rsp);
1067 match_check(struct softnic_table_rule_match *match,
1071 struct softnic_table *table;
1073 if (match == NULL ||
1075 table_id >= p->n_tables)
1078 table = &p->table[table_id];
1079 if (match->match_type != table->params.match_type)
1082 switch (match->match_type) {
1085 struct softnic_table_acl_params *t = &table->params.match.acl;
1086 struct softnic_table_rule_match_acl *r = &match->match.acl;
1088 if ((r->ip_version && (t->ip_version == 0)) ||
1089 ((r->ip_version == 0) && t->ip_version))
1092 if (r->ip_version) {
1093 if (r->sa_depth > 32 ||
1097 if (r->sa_depth > 128 ||
1112 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1113 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1115 if ((r->ip_version && (t->key_size != 4)) ||
1116 ((r->ip_version == 0) && (t->key_size != 16)))
1119 if (r->ip_version) {
1138 action_check(struct softnic_table_rule_action *action,
1142 struct softnic_table_action_profile *ap;
1144 if (action == NULL ||
1146 table_id >= p->n_tables)
1149 ap = p->table[table_id].ap;
1150 if (action->action_mask != ap->params.action_mask)
1153 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1154 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1155 action->fwd.id >= p->n_ports_out)
1158 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1159 action->fwd.id >= p->n_tables)
1163 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1164 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1165 uint32_t tc_mask1 = action->mtr.tc_mask;
1167 if (tc_mask1 != tc_mask0)
1171 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1172 uint32_t n_subports_per_port =
1173 ap->params.tm.n_subports_per_port;
1174 uint32_t n_pipes_per_subport =
1175 ap->params.tm.n_pipes_per_subport;
1176 uint32_t subport_id = action->tm.subport_id;
1177 uint32_t pipe_id = action->tm.pipe_id;
1179 if (subport_id >= n_subports_per_port ||
1180 pipe_id >= n_pipes_per_subport)
1184 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1185 uint64_t encap_mask = ap->params.encap.encap_mask;
1186 enum rte_table_action_encap_type type = action->encap.type;
1188 if ((encap_mask & (1LLU << type)) == 0)
1192 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1193 int ip_version0 = ap->params.common.ip_version;
1194 int ip_version1 = action->nat.ip_version;
1196 if ((ip_version1 && (ip_version0 == 0)) ||
1197 ((ip_version1 == 0) && ip_version0))
1205 action_default_check(struct softnic_table_rule_action *action,
1209 if (action == NULL ||
1210 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1212 table_id >= p->n_tables)
1215 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1216 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1217 action->fwd.id >= p->n_ports_out)
1220 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1221 action->fwd.id >= p->n_tables)
1228 union table_rule_match_low_level {
1229 struct rte_table_acl_rule_add_params acl_add;
1230 struct rte_table_acl_rule_delete_params acl_delete;
1231 struct rte_table_array_key array;
1232 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1233 struct rte_table_lpm_key lpm_ipv4;
1234 struct rte_table_lpm_ipv6_key lpm_ipv6;
1238 match_convert(struct softnic_table_rule_match *mh,
1239 union table_rule_match_low_level *ml,
1243 action_convert(struct rte_table_action *a,
1244 struct softnic_table_rule_action *action,
1245 struct rte_pipeline_table_entry *data);
1248 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1249 const char *pipeline_name,
1251 struct softnic_table_rule_match *match,
1252 struct softnic_table_rule_action *action,
1256 struct pipeline_msg_req *req;
1257 struct pipeline_msg_rsp *rsp;
1260 /* Check input params */
1261 if (pipeline_name == NULL ||
1267 p = softnic_pipeline_find(softnic, pipeline_name);
1269 table_id >= p->n_tables ||
1270 match_check(match, p, table_id) ||
1271 action_check(action, p, table_id))
1274 if (!pipeline_is_running(p)) {
1275 struct rte_table_action *a = p->table[table_id].a;
1276 union table_rule_match_low_level match_ll;
1277 struct rte_pipeline_table_entry *data_in, *data_out;
1281 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1285 /* Table match-action rule conversion */
1286 data_in = (struct rte_pipeline_table_entry *)buffer;
1288 status = match_convert(match, &match_ll, 1);
1294 status = action_convert(a, action, data_in);
1300 /* Add rule (match, action) to table */
1301 status = rte_pipeline_table_entry_add(p->p,
1312 /* Write Response */
1319 /* Allocate request */
1320 req = pipeline_msg_alloc();
1325 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1327 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1328 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1330 /* Send request and wait for response */
1331 rsp = pipeline_msg_send_recv(p, req);
1336 status = rsp->status;
1338 *data = rsp->table_rule_add.data;
1341 pipeline_msg_free(rsp);
1347 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1348 const char *pipeline_name,
1350 struct softnic_table_rule_action *action,
1354 struct pipeline_msg_req *req;
1355 struct pipeline_msg_rsp *rsp;
1358 /* Check input params */
1359 if (pipeline_name == NULL ||
1364 p = softnic_pipeline_find(softnic, pipeline_name);
1366 table_id >= p->n_tables ||
1367 action_default_check(action, p, table_id))
1370 if (!pipeline_is_running(p)) {
1371 struct rte_pipeline_table_entry *data_in, *data_out;
1374 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1379 data_in = (struct rte_pipeline_table_entry *)buffer;
1381 data_in->action = action->fwd.action;
1382 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1383 data_in->port_id = action->fwd.id;
1384 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1385 data_in->table_id = action->fwd.id;
1387 /* Add default rule to table */
1388 status = rte_pipeline_table_default_entry_add(p->p,
1397 /* Write Response */
1404 /* Allocate request */
1405 req = pipeline_msg_alloc();
1410 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1412 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1414 /* Send request and wait for response */
1415 rsp = pipeline_msg_send_recv(p, req);
1420 status = rsp->status;
1422 *data = rsp->table_rule_add_default.data;
1425 pipeline_msg_free(rsp);
1431 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1432 const char *pipeline_name,
1434 struct softnic_table_rule_match *match,
1435 struct softnic_table_rule_action *action,
1440 struct pipeline_msg_req *req;
1441 struct pipeline_msg_rsp *rsp;
1445 /* Check input params */
1446 if (pipeline_name == NULL ||
1454 p = softnic_pipeline_find(softnic, pipeline_name);
1456 table_id >= p->n_tables)
1459 for (i = 0; i < *n_rules; i++)
1460 if (match_check(match, p, table_id) ||
1461 action_check(action, p, table_id))
1464 if (!pipeline_is_running(p)) {
1465 struct rte_table_action *a = p->table[table_id].a;
1466 union table_rule_match_low_level *match_ll;
1468 void **match_ll_ptr;
1469 struct rte_pipeline_table_entry **action_ll_ptr;
1470 struct rte_pipeline_table_entry **entries_ptr =
1471 (struct rte_pipeline_table_entry **)data;
1473 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1476 /* Memory allocation */
1477 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1478 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1479 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1481 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1482 found = calloc(*n_rules, sizeof(int));
1484 if (match_ll == NULL ||
1485 action_ll == NULL ||
1486 match_ll_ptr == NULL ||
1487 action_ll_ptr == NULL ||
1491 for (i = 0; i < *n_rules; i++) {
1492 match_ll_ptr[i] = (void *)&match_ll[i];
1494 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1497 /* Rule match conversion */
1498 for (i = 0; i < *n_rules; i++) {
1499 status = match_convert(&match[i], match_ll_ptr[i], 1);
1504 /* Rule action conversion */
1505 for (i = 0; i < *n_rules; i++) {
1506 status = action_convert(a, &action[i], action_ll_ptr[i]);
1511 /* Add rule (match, action) to table */
1513 status = rte_pipeline_table_entry_add_bulk(p->p,
1523 for (i = 0; i < *n_rules; i++) {
1524 status = rte_pipeline_table_entry_add(p->p,
1539 free(action_ll_ptr);
1548 free(action_ll_ptr);
1557 /* Allocate request */
1558 req = pipeline_msg_alloc();
1563 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1565 req->table_rule_add_bulk.match = match;
1566 req->table_rule_add_bulk.action = action;
1567 req->table_rule_add_bulk.data = data;
1568 req->table_rule_add_bulk.n_rules = *n_rules;
1569 req->table_rule_add_bulk.bulk =
1570 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1572 /* Send request and wait for response */
1573 rsp = pipeline_msg_send_recv(p, req);
1578 status = rsp->status;
1580 *n_rules = rsp->table_rule_add_bulk.n_rules;
1583 pipeline_msg_free(rsp);
1589 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1590 const char *pipeline_name,
1592 struct softnic_table_rule_match *match)
1595 struct pipeline_msg_req *req;
1596 struct pipeline_msg_rsp *rsp;
1599 /* Check input params */
1600 if (pipeline_name == NULL ||
1604 p = softnic_pipeline_find(softnic, pipeline_name);
1606 table_id >= p->n_tables ||
1607 match_check(match, p, table_id))
1610 if (!pipeline_is_running(p)) {
1611 union table_rule_match_low_level match_ll;
1614 status = match_convert(match, &match_ll, 0);
1618 status = rte_pipeline_table_entry_delete(p->p,
1627 /* Allocate request */
1628 req = pipeline_msg_alloc();
1633 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1635 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1637 /* Send request and wait for response */
1638 rsp = pipeline_msg_send_recv(p, req);
1643 status = rsp->status;
1646 pipeline_msg_free(rsp);
1652 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1653 const char *pipeline_name,
1657 struct pipeline_msg_req *req;
1658 struct pipeline_msg_rsp *rsp;
1661 /* Check input params */
1662 if (pipeline_name == NULL)
1665 p = softnic_pipeline_find(softnic, pipeline_name);
1667 table_id >= p->n_tables)
1670 if (!pipeline_is_running(p)) {
1671 status = rte_pipeline_table_default_entry_delete(p->p,
1678 /* Allocate request */
1679 req = pipeline_msg_alloc();
1684 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1687 /* Send request and wait for response */
1688 rsp = pipeline_msg_send_recv(p, req);
1693 status = rsp->status;
1696 pipeline_msg_free(rsp);
1702 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1703 const char *pipeline_name,
1706 struct rte_table_action_stats_counters *stats,
1710 struct pipeline_msg_req *req;
1711 struct pipeline_msg_rsp *rsp;
1714 /* Check input params */
1715 if (pipeline_name == NULL ||
1720 p = softnic_pipeline_find(softnic, pipeline_name);
1722 table_id >= p->n_tables)
1725 if (!pipeline_is_running(p)) {
1726 struct rte_table_action *a = p->table[table_id].a;
1728 status = rte_table_action_stats_read(a,
1736 /* Allocate request */
1737 req = pipeline_msg_alloc();
1742 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1744 req->table_rule_stats_read.data = data;
1745 req->table_rule_stats_read.clear = clear;
1747 /* Send request and wait for response */
1748 rsp = pipeline_msg_send_recv(p, req);
1753 status = rsp->status;
1755 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1758 pipeline_msg_free(rsp);
1764 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1765 const char *pipeline_name,
1767 uint32_t meter_profile_id,
1768 struct rte_table_action_meter_profile *profile)
1771 struct pipeline_msg_req *req;
1772 struct pipeline_msg_rsp *rsp;
1773 struct softnic_table *table;
1774 struct softnic_table_meter_profile *mp;
1777 /* Check input params */
1778 if (pipeline_name == NULL ||
1782 p = softnic_pipeline_find(softnic, pipeline_name);
1784 table_id >= p->n_tables)
1787 table = &p->table[table_id];
1788 mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
1792 /* Resource Allocation */
1793 mp = calloc(1, sizeof(struct softnic_table_meter_profile));
1797 mp->meter_profile_id = meter_profile_id;
1798 memcpy(&mp->profile, profile, sizeof(mp->profile));
1800 if (!pipeline_is_running(p)) {
1801 status = rte_table_action_meter_profile_add(table->a,
1809 /* Add profile to the table. */
1810 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1815 /* Allocate request */
1816 req = pipeline_msg_alloc();
1823 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1825 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1826 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1828 /* Send request and wait for response */
1829 rsp = pipeline_msg_send_recv(p, req);
1836 status = rsp->status;
1838 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1843 pipeline_msg_free(rsp);
1849 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1850 const char *pipeline_name,
1852 uint32_t meter_profile_id)
1855 struct pipeline_msg_req *req;
1856 struct pipeline_msg_rsp *rsp;
1859 /* Check input params */
1860 if (pipeline_name == NULL)
1863 p = softnic_pipeline_find(softnic, pipeline_name);
1865 table_id >= p->n_tables)
1868 if (!pipeline_is_running(p)) {
1869 struct rte_table_action *a = p->table[table_id].a;
1871 status = rte_table_action_meter_profile_delete(a,
1877 /* Allocate request */
1878 req = pipeline_msg_alloc();
1883 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1885 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1887 /* Send request and wait for response */
1888 rsp = pipeline_msg_send_recv(p, req);
1893 status = rsp->status;
1896 pipeline_msg_free(rsp);
1902 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1903 const char *pipeline_name,
1907 struct rte_table_action_mtr_counters *stats,
1911 struct pipeline_msg_req *req;
1912 struct pipeline_msg_rsp *rsp;
1915 /* Check input params */
1916 if (pipeline_name == NULL ||
1921 p = softnic_pipeline_find(softnic, pipeline_name);
1923 table_id >= p->n_tables)
1926 if (!pipeline_is_running(p)) {
1927 struct rte_table_action *a = p->table[table_id].a;
1929 status = rte_table_action_meter_read(a,
1938 /* Allocate request */
1939 req = pipeline_msg_alloc();
1944 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1946 req->table_rule_mtr_read.data = data;
1947 req->table_rule_mtr_read.tc_mask = tc_mask;
1948 req->table_rule_mtr_read.clear = clear;
1950 /* Send request and wait for response */
1951 rsp = pipeline_msg_send_recv(p, req);
1956 status = rsp->status;
1958 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1961 pipeline_msg_free(rsp);
1967 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1968 const char *pipeline_name,
1971 struct rte_table_action_dscp_table *dscp_table)
1974 struct pipeline_msg_req *req;
1975 struct pipeline_msg_rsp *rsp;
1978 /* Check input params */
1979 if (pipeline_name == NULL ||
1983 p = softnic_pipeline_find(softnic, pipeline_name);
1985 table_id >= p->n_tables)
1988 if (!pipeline_is_running(p)) {
1989 struct rte_table_action *a = p->table[table_id].a;
1991 status = rte_table_action_dscp_table_update(a,
1995 /* Update table dscp table */
1997 memcpy(&p->table[table_id].dscp_table, dscp_table,
1998 sizeof(p->table[table_id].dscp_table));
2003 /* Allocate request */
2004 req = pipeline_msg_alloc();
2009 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
2011 req->table_dscp_table_update.dscp_mask = dscp_mask;
2012 memcpy(&req->table_dscp_table_update.dscp_table,
2013 dscp_table, sizeof(*dscp_table));
2015 /* Send request and wait for response */
2016 rsp = pipeline_msg_send_recv(p, req);
2021 status = rsp->status;
2023 /* Update table dscp table */
2025 memcpy(&p->table[table_id].dscp_table, dscp_table,
2026 sizeof(p->table[table_id].dscp_table));
2029 pipeline_msg_free(rsp);
2035 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
2036 const char *pipeline_name,
2039 struct rte_table_action_ttl_counters *stats,
2043 struct pipeline_msg_req *req;
2044 struct pipeline_msg_rsp *rsp;
2047 /* Check input params */
2048 if (pipeline_name == NULL ||
2053 p = softnic_pipeline_find(softnic, pipeline_name);
2055 table_id >= p->n_tables)
2058 if (!pipeline_is_running(p)) {
2059 struct rte_table_action *a = p->table[table_id].a;
2061 status = rte_table_action_ttl_read(a,
2069 /* Allocate request */
2070 req = pipeline_msg_alloc();
2075 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
2077 req->table_rule_ttl_read.data = data;
2078 req->table_rule_ttl_read.clear = clear;
2080 /* Send request and wait for response */
2081 rsp = pipeline_msg_send_recv(p, req);
2086 status = rsp->status;
2088 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2091 pipeline_msg_free(rsp);
2097 * Data plane threads: message handling
2099 static inline struct pipeline_msg_req *
2100 pipeline_msg_recv(struct rte_ring *msgq_req)
2102 struct pipeline_msg_req *req;
2104 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2113 pipeline_msg_send(struct rte_ring *msgq_rsp,
2114 struct pipeline_msg_rsp *rsp)
2119 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2120 } while (status == -ENOBUFS);
2123 static struct pipeline_msg_rsp *
2124 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2125 struct pipeline_msg_req *req)
2127 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2128 uint32_t port_id = req->id;
2129 int clear = req->port_in_stats_read.clear;
2131 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2133 &rsp->port_in_stats_read.stats,
2139 static struct pipeline_msg_rsp *
2140 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2141 struct pipeline_msg_req *req)
2143 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2144 uint32_t port_id = req->id;
2146 rsp->status = rte_pipeline_port_in_enable(p->p,
2152 static struct pipeline_msg_rsp *
2153 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2154 struct pipeline_msg_req *req)
2156 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2157 uint32_t port_id = req->id;
2159 rsp->status = rte_pipeline_port_in_disable(p->p,
2165 static struct pipeline_msg_rsp *
2166 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2167 struct pipeline_msg_req *req)
2169 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2170 uint32_t port_id = req->id;
2171 int clear = req->port_out_stats_read.clear;
2173 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2175 &rsp->port_out_stats_read.stats,
2181 static struct pipeline_msg_rsp *
2182 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2183 struct pipeline_msg_req *req)
2185 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2186 uint32_t port_id = req->id;
2187 int clear = req->table_stats_read.clear;
2189 rsp->status = rte_pipeline_table_stats_read(p->p,
2191 &rsp->table_stats_read.stats,
2198 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2203 switch (depth / 32) {
2213 depth32[1] = depth - 32;
2221 depth32[2] = depth - 64;
2229 depth32[3] = depth - 96;
2245 match_convert(struct softnic_table_rule_match *mh,
2246 union table_rule_match_low_level *ml,
2249 memset(ml, 0, sizeof(*ml));
2251 switch (mh->match_type) {
2253 if (mh->match.acl.ip_version)
2255 ml->acl_add.field_value[0].value.u8 =
2256 mh->match.acl.proto;
2257 ml->acl_add.field_value[0].mask_range.u8 =
2258 mh->match.acl.proto_mask;
2260 ml->acl_add.field_value[1].value.u32 =
2261 mh->match.acl.ipv4.sa;
2262 ml->acl_add.field_value[1].mask_range.u32 =
2263 mh->match.acl.sa_depth;
2265 ml->acl_add.field_value[2].value.u32 =
2266 mh->match.acl.ipv4.da;
2267 ml->acl_add.field_value[2].mask_range.u32 =
2268 mh->match.acl.da_depth;
2270 ml->acl_add.field_value[3].value.u16 =
2272 ml->acl_add.field_value[3].mask_range.u16 =
2275 ml->acl_add.field_value[4].value.u16 =
2277 ml->acl_add.field_value[4].mask_range.u16 =
2280 ml->acl_add.priority =
2281 (int32_t)mh->match.acl.priority;
2283 ml->acl_delete.field_value[0].value.u8 =
2284 mh->match.acl.proto;
2285 ml->acl_delete.field_value[0].mask_range.u8 =
2286 mh->match.acl.proto_mask;
2288 ml->acl_delete.field_value[1].value.u32 =
2289 mh->match.acl.ipv4.sa;
2290 ml->acl_delete.field_value[1].mask_range.u32 =
2291 mh->match.acl.sa_depth;
2293 ml->acl_delete.field_value[2].value.u32 =
2294 mh->match.acl.ipv4.da;
2295 ml->acl_delete.field_value[2].mask_range.u32 =
2296 mh->match.acl.da_depth;
2298 ml->acl_delete.field_value[3].value.u16 =
2300 ml->acl_delete.field_value[3].mask_range.u16 =
2303 ml->acl_delete.field_value[4].value.u16 =
2305 ml->acl_delete.field_value[4].mask_range.u16 =
2311 (uint32_t *)mh->match.acl.ipv6.sa;
2313 (uint32_t *)mh->match.acl.ipv6.da;
2314 uint32_t sa32_depth[4], da32_depth[4];
2317 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2322 status = match_convert_ipv6_depth(
2323 mh->match.acl.da_depth,
2328 ml->acl_add.field_value[0].value.u8 =
2329 mh->match.acl.proto;
2330 ml->acl_add.field_value[0].mask_range.u8 =
2331 mh->match.acl.proto_mask;
2333 ml->acl_add.field_value[1].value.u32 =
2334 rte_be_to_cpu_32(sa32[0]);
2335 ml->acl_add.field_value[1].mask_range.u32 =
2337 ml->acl_add.field_value[2].value.u32 =
2338 rte_be_to_cpu_32(sa32[1]);
2339 ml->acl_add.field_value[2].mask_range.u32 =
2341 ml->acl_add.field_value[3].value.u32 =
2342 rte_be_to_cpu_32(sa32[2]);
2343 ml->acl_add.field_value[3].mask_range.u32 =
2345 ml->acl_add.field_value[4].value.u32 =
2346 rte_be_to_cpu_32(sa32[3]);
2347 ml->acl_add.field_value[4].mask_range.u32 =
2350 ml->acl_add.field_value[5].value.u32 =
2351 rte_be_to_cpu_32(da32[0]);
2352 ml->acl_add.field_value[5].mask_range.u32 =
2354 ml->acl_add.field_value[6].value.u32 =
2355 rte_be_to_cpu_32(da32[1]);
2356 ml->acl_add.field_value[6].mask_range.u32 =
2358 ml->acl_add.field_value[7].value.u32 =
2359 rte_be_to_cpu_32(da32[2]);
2360 ml->acl_add.field_value[7].mask_range.u32 =
2362 ml->acl_add.field_value[8].value.u32 =
2363 rte_be_to_cpu_32(da32[3]);
2364 ml->acl_add.field_value[8].mask_range.u32 =
2367 ml->acl_add.field_value[9].value.u16 =
2369 ml->acl_add.field_value[9].mask_range.u16 =
2372 ml->acl_add.field_value[10].value.u16 =
2374 ml->acl_add.field_value[10].mask_range.u16 =
2377 ml->acl_add.priority =
2378 (int32_t)mh->match.acl.priority;
2381 (uint32_t *)mh->match.acl.ipv6.sa;
2383 (uint32_t *)mh->match.acl.ipv6.da;
2384 uint32_t sa32_depth[4], da32_depth[4];
2387 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2392 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2397 ml->acl_delete.field_value[0].value.u8 =
2398 mh->match.acl.proto;
2399 ml->acl_delete.field_value[0].mask_range.u8 =
2400 mh->match.acl.proto_mask;
2402 ml->acl_delete.field_value[1].value.u32 =
2403 rte_be_to_cpu_32(sa32[0]);
2404 ml->acl_delete.field_value[1].mask_range.u32 =
2406 ml->acl_delete.field_value[2].value.u32 =
2407 rte_be_to_cpu_32(sa32[1]);
2408 ml->acl_delete.field_value[2].mask_range.u32 =
2410 ml->acl_delete.field_value[3].value.u32 =
2411 rte_be_to_cpu_32(sa32[2]);
2412 ml->acl_delete.field_value[3].mask_range.u32 =
2414 ml->acl_delete.field_value[4].value.u32 =
2415 rte_be_to_cpu_32(sa32[3]);
2416 ml->acl_delete.field_value[4].mask_range.u32 =
2419 ml->acl_delete.field_value[5].value.u32 =
2420 rte_be_to_cpu_32(da32[0]);
2421 ml->acl_delete.field_value[5].mask_range.u32 =
2423 ml->acl_delete.field_value[6].value.u32 =
2424 rte_be_to_cpu_32(da32[1]);
2425 ml->acl_delete.field_value[6].mask_range.u32 =
2427 ml->acl_delete.field_value[7].value.u32 =
2428 rte_be_to_cpu_32(da32[2]);
2429 ml->acl_delete.field_value[7].mask_range.u32 =
2431 ml->acl_delete.field_value[8].value.u32 =
2432 rte_be_to_cpu_32(da32[3]);
2433 ml->acl_delete.field_value[8].mask_range.u32 =
2436 ml->acl_delete.field_value[9].value.u16 =
2438 ml->acl_delete.field_value[9].mask_range.u16 =
2441 ml->acl_delete.field_value[10].value.u16 =
2443 ml->acl_delete.field_value[10].mask_range.u16 =
2449 ml->array.pos = mh->match.array.pos;
2453 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2457 if (mh->match.lpm.ip_version) {
2458 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2459 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2461 memcpy(ml->lpm_ipv6.ip,
2462 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2463 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2474 action_convert(struct rte_table_action *a,
2475 struct softnic_table_rule_action *action,
2476 struct rte_pipeline_table_entry *data)
2481 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2482 status = rte_table_action_apply(a,
2484 RTE_TABLE_ACTION_FWD,
2491 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2492 status = rte_table_action_apply(a,
2494 RTE_TABLE_ACTION_LB,
2501 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2502 status = rte_table_action_apply(a,
2504 RTE_TABLE_ACTION_MTR,
2511 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2512 status = rte_table_action_apply(a,
2514 RTE_TABLE_ACTION_TM,
2521 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2522 status = rte_table_action_apply(a,
2524 RTE_TABLE_ACTION_ENCAP,
2531 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2532 status = rte_table_action_apply(a,
2534 RTE_TABLE_ACTION_NAT,
2541 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2542 status = rte_table_action_apply(a,
2544 RTE_TABLE_ACTION_TTL,
2551 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2552 status = rte_table_action_apply(a,
2554 RTE_TABLE_ACTION_STATS,
2561 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2562 status = rte_table_action_apply(a,
2564 RTE_TABLE_ACTION_TIME,
2571 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2572 status = rte_table_action_apply(a,
2574 RTE_TABLE_ACTION_TAG,
2581 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2582 status = rte_table_action_apply(a,
2584 RTE_TABLE_ACTION_DECAP,
2591 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2592 status = rte_table_action_apply(a,
2594 RTE_TABLE_ACTION_SYM_CRYPTO,
2595 &action->sym_crypto);
2604 static struct pipeline_msg_rsp *
2605 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2606 struct pipeline_msg_req *req)
2608 union table_rule_match_low_level match_ll;
2609 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2610 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2611 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2612 struct rte_pipeline_table_entry *data_in, *data_out;
2613 uint32_t table_id = req->id;
2614 int key_found, status;
2615 struct rte_table_action *a = p->table_data[table_id].a;
2618 memset(p->buffer, 0, sizeof(p->buffer));
2619 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2621 status = match_convert(match, &match_ll, 1);
2627 status = action_convert(a, action, data_in);
2633 status = rte_pipeline_table_entry_add(p->p,
2644 /* Write response */
2646 rsp->table_rule_add.data = data_out;
2651 static struct pipeline_msg_rsp *
2652 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2653 struct pipeline_msg_req *req)
2655 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2656 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2657 struct rte_pipeline_table_entry *data_in, *data_out;
2658 uint32_t table_id = req->id;
2662 memset(p->buffer, 0, sizeof(p->buffer));
2663 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2665 data_in->action = action->fwd.action;
2666 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2667 data_in->port_id = action->fwd.id;
2668 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2669 data_in->table_id = action->fwd.id;
2671 /* Add default rule to table */
2672 status = rte_pipeline_table_default_entry_add(p->p,
2681 /* Write response */
2683 rsp->table_rule_add_default.data = data_out;
2688 static struct pipeline_msg_rsp *
2689 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2690 struct pipeline_msg_req *req)
2692 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2694 uint32_t table_id = req->id;
2695 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2696 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2697 struct rte_pipeline_table_entry **data =
2698 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2699 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2700 uint32_t bulk = req->table_rule_add_bulk.bulk;
2702 struct rte_table_action *a = p->table_data[table_id].a;
2703 union table_rule_match_low_level *match_ll;
2705 void **match_ll_ptr;
2706 struct rte_pipeline_table_entry **action_ll_ptr;
2710 /* Memory allocation */
2711 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2712 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2713 match_ll_ptr = calloc(n_rules, sizeof(void *));
2715 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2716 found = calloc(n_rules, sizeof(int));
2718 if (match_ll == NULL ||
2719 action_ll == NULL ||
2720 match_ll_ptr == NULL ||
2721 action_ll_ptr == NULL ||
2725 for (i = 0; i < n_rules; i++) {
2726 match_ll_ptr[i] = (void *)&match_ll[i];
2728 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2731 /* Rule match conversion */
2732 for (i = 0; i < n_rules; i++) {
2733 status = match_convert(&match[i], match_ll_ptr[i], 1);
2738 /* Rule action conversion */
2739 for (i = 0; i < n_rules; i++) {
2740 status = action_convert(a, &action[i], action_ll_ptr[i]);
2745 /* Add rule (match, action) to table */
2747 status = rte_pipeline_table_entry_add_bulk(p->p,
2757 for (i = 0; i < n_rules; i++) {
2758 status = rte_pipeline_table_entry_add(p->p,
2771 /* Write response */
2773 rsp->table_rule_add_bulk.n_rules = n_rules;
2777 free(action_ll_ptr);
2786 free(action_ll_ptr);
2792 rsp->table_rule_add_bulk.n_rules = 0;
2796 static struct pipeline_msg_rsp *
2797 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2798 struct pipeline_msg_req *req)
2800 union table_rule_match_low_level match_ll;
2801 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2802 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2803 uint32_t table_id = req->id;
2804 int key_found, status;
2806 status = match_convert(match, &match_ll, 0);
2812 rsp->status = rte_pipeline_table_entry_delete(p->p,
2821 static struct pipeline_msg_rsp *
2822 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2823 struct pipeline_msg_req *req)
2825 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2826 uint32_t table_id = req->id;
2828 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2835 static struct pipeline_msg_rsp *
2836 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2837 struct pipeline_msg_req *req)
2839 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2840 uint32_t table_id = req->id;
2841 void *data = req->table_rule_stats_read.data;
2842 int clear = req->table_rule_stats_read.clear;
2843 struct rte_table_action *a = p->table_data[table_id].a;
2845 rsp->status = rte_table_action_stats_read(a,
2847 &rsp->table_rule_stats_read.stats,
2853 static struct pipeline_msg_rsp *
2854 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2855 struct pipeline_msg_req *req)
2857 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2858 uint32_t table_id = req->id;
2859 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2860 struct rte_table_action_meter_profile *profile =
2861 &req->table_mtr_profile_add.profile;
2862 struct rte_table_action *a = p->table_data[table_id].a;
2864 rsp->status = rte_table_action_meter_profile_add(a,
2871 static struct pipeline_msg_rsp *
2872 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2873 struct pipeline_msg_req *req)
2875 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2876 uint32_t table_id = req->id;
2877 uint32_t meter_profile_id =
2878 req->table_mtr_profile_delete.meter_profile_id;
2879 struct rte_table_action *a = p->table_data[table_id].a;
2881 rsp->status = rte_table_action_meter_profile_delete(a,
2887 static struct pipeline_msg_rsp *
2888 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2889 struct pipeline_msg_req *req)
2891 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2892 uint32_t table_id = req->id;
2893 void *data = req->table_rule_mtr_read.data;
2894 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2895 int clear = req->table_rule_mtr_read.clear;
2896 struct rte_table_action *a = p->table_data[table_id].a;
2898 rsp->status = rte_table_action_meter_read(a,
2901 &rsp->table_rule_mtr_read.stats,
2907 static struct pipeline_msg_rsp *
2908 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2909 struct pipeline_msg_req *req)
2911 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2912 uint32_t table_id = req->id;
2913 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2914 struct rte_table_action_dscp_table *dscp_table =
2915 &req->table_dscp_table_update.dscp_table;
2916 struct rte_table_action *a = p->table_data[table_id].a;
2918 rsp->status = rte_table_action_dscp_table_update(a,
2925 static struct pipeline_msg_rsp *
2926 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2927 struct pipeline_msg_req *req)
2929 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2930 uint32_t table_id = req->id;
2931 void *data = req->table_rule_ttl_read.data;
2932 int clear = req->table_rule_ttl_read.clear;
2933 struct rte_table_action *a = p->table_data[table_id].a;
2935 rsp->status = rte_table_action_ttl_read(a,
2937 &rsp->table_rule_ttl_read.stats,
2944 pipeline_msg_handle(struct pipeline_data *p)
2947 struct pipeline_msg_req *req;
2948 struct pipeline_msg_rsp *rsp;
2950 req = pipeline_msg_recv(p->msgq_req);
2954 switch (req->type) {
2955 case PIPELINE_REQ_PORT_IN_STATS_READ:
2956 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2959 case PIPELINE_REQ_PORT_IN_ENABLE:
2960 rsp = pipeline_msg_handle_port_in_enable(p, req);
2963 case PIPELINE_REQ_PORT_IN_DISABLE:
2964 rsp = pipeline_msg_handle_port_in_disable(p, req);
2967 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2968 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2971 case PIPELINE_REQ_TABLE_STATS_READ:
2972 rsp = pipeline_msg_handle_table_stats_read(p, req);
2975 case PIPELINE_REQ_TABLE_RULE_ADD:
2976 rsp = pipeline_msg_handle_table_rule_add(p, req);
2979 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2980 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2983 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2984 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2987 case PIPELINE_REQ_TABLE_RULE_DELETE:
2988 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2991 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2992 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2995 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2996 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2999 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
3000 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
3003 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
3004 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
3007 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
3008 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
3011 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
3012 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
3015 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
3016 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
3020 rsp = (struct pipeline_msg_rsp *)req;
3024 pipeline_msg_send(p->msgq_rsp, rsp);
3029 * Data plane threads: main
3032 rte_pmd_softnic_run_internal(void *arg)
3034 struct rte_eth_dev *dev = arg;
3035 struct pmd_internals *softnic;
3036 struct softnic_thread_data *t;
3037 uint32_t thread_id, j;
3039 softnic = dev->data->dev_private;
3040 thread_id = rte_lcore_id();
3041 t = &softnic->thread_data[thread_id];
3045 for (j = 0; j < t->n_pipelines; j++)
3046 rte_pipeline_run(t->p[j]);
3049 if ((t->iter & 0xFLLU) == 0) {
3050 uint64_t time = rte_get_tsc_cycles();
3051 uint64_t time_next_min = UINT64_MAX;
3053 if (time < t->time_next_min)
3056 /* Pipeline message queues */
3057 for (j = 0; j < t->n_pipelines; j++) {
3058 struct pipeline_data *p =
3059 &t->pipeline_data[j];
3060 uint64_t time_next = p->time_next;
3062 if (time_next <= time) {
3063 pipeline_msg_handle(p);
3064 rte_pipeline_flush(p->p);
3065 time_next = time + p->timer_period;
3066 p->time_next = time_next;
3069 if (time_next < time_next_min)
3070 time_next_min = time_next;
3073 /* Thread message queues */
3075 uint64_t time_next = t->time_next;
3077 if (time_next <= time) {
3078 thread_msg_handle(t);
3079 time_next = time + t->timer_period;
3080 t->time_next = time_next;
3083 if (time_next < time_next_min)
3084 time_next_min = time_next;
3087 t->time_next_min = time_next_min;
3094 rte_pmd_softnic_run(uint16_t port_id)
3096 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3098 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
3099 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
3102 return (int)rte_pmd_softnic_run_internal(dev);