1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
7 #include <rte_common.h>
8 #include <rte_cycles.h>
10 #include <rte_service_component.h>
13 #include <rte_table_acl.h>
14 #include <rte_table_array.h>
15 #include <rte_table_hash.h>
16 #include <rte_table_lpm.h>
17 #include <rte_table_lpm_ipv6.h>
18 #include "rte_eth_softnic_internals.h"
21 * Main thread: data plane thread init
24 softnic_thread_free(struct pmd_internals *softnic)
28 RTE_LCORE_FOREACH_WORKER(i) {
29 struct softnic_thread *t = &softnic->thread[i];
33 rte_ring_free(t->msgq_req);
36 rte_ring_free(t->msgq_rsp);
41 softnic_thread_init(struct pmd_internals *softnic)
45 for (i = 0; i < RTE_MAX_LCORE; i++) {
46 char ring_name[NAME_MAX];
47 struct rte_ring *msgq_req, *msgq_rsp;
48 struct softnic_thread *t = &softnic->thread[i];
49 struct softnic_thread_data *t_data = &softnic->thread_data[i];
50 uint32_t cpu_id = rte_lcore_to_socket_id(i);
53 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ",
57 msgq_req = rte_ring_create(ring_name,
60 RING_F_SP_ENQ | RING_F_SC_DEQ);
62 if (msgq_req == NULL) {
63 softnic_thread_free(softnic);
67 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP",
71 msgq_rsp = rte_ring_create(ring_name,
74 RING_F_SP_ENQ | RING_F_SC_DEQ);
76 if (msgq_rsp == NULL) {
77 softnic_thread_free(softnic);
81 /* Main thread records */
82 t->msgq_req = msgq_req;
83 t->msgq_rsp = msgq_rsp;
84 t->service_id = UINT32_MAX;
86 /* Data plane thread records */
87 t_data->n_pipelines = 0;
88 t_data->msgq_req = msgq_req;
89 t_data->msgq_rsp = msgq_rsp;
90 t_data->timer_period =
91 (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
92 t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
93 t_data->time_next_min = t_data->time_next;
100 thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id)
102 if (thread_id == rte_get_main_lcore())
103 return 0; /* FALSE */
105 if (softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_SERVICE))
107 if (!softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_RTE))
110 return 0; /* FALSE */
114 thread_is_running(uint32_t thread_id)
116 enum rte_lcore_state_t thread_state;
118 thread_state = rte_eal_get_lcore_state(thread_id);
119 return (thread_state == RUNNING)? 1 : 0;
123 rte_pmd_softnic_run_internal(void *arg);
126 thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
128 struct rte_service_spec service_params;
129 struct softnic_thread *t = &softnic->thread[thread_id];
130 struct rte_eth_dev *dev;
134 dev = rte_eth_dev_get_by_name(softnic->params.name);
138 snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
139 softnic->params.name,
141 service_params.callback = rte_pmd_softnic_run_internal;
142 service_params.callback_userdata = dev;
143 service_params.capabilities = 0;
144 service_params.socket_id = (int)softnic->params.cpu_id;
146 /* service register */
147 status = rte_service_component_register(&service_params, &t->service_id);
151 status = rte_service_component_runstate_set(t->service_id, 1);
153 rte_service_component_unregister(t->service_id);
154 t->service_id = UINT32_MAX;
158 status = rte_service_runstate_set(t->service_id, 1);
160 rte_service_component_runstate_set(t->service_id, 0);
161 rte_service_component_unregister(t->service_id);
162 t->service_id = UINT32_MAX;
166 /* service map to thread */
167 status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
169 rte_service_runstate_set(t->service_id, 0);
170 rte_service_component_runstate_set(t->service_id, 0);
171 rte_service_component_unregister(t->service_id);
172 t->service_id = UINT32_MAX;
180 thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
182 struct softnic_thread *t = &softnic->thread[thread_id];
184 /* service unmap from thread */
185 rte_service_map_lcore_set(t->service_id, thread_id, 0);
187 /* service unregister */
188 rte_service_runstate_set(t->service_id, 0);
189 rte_service_component_runstate_set(t->service_id, 0);
190 rte_service_component_unregister(t->service_id);
192 t->service_id = UINT32_MAX;
196 * Pipeline is running when:
197 * (A) Pipeline is mapped to a data plane thread AND
198 * (B) Its data plane thread is in RUNNING state.
201 pipeline_is_running(struct pipeline *p)
206 return thread_is_running(p->thread_id);
210 * Main thread & data plane threads: message passing
212 enum thread_req_type {
213 THREAD_REQ_PIPELINE_ENABLE = 0,
214 THREAD_REQ_PIPELINE_DISABLE,
218 struct thread_msg_req {
219 enum thread_req_type type;
223 struct rte_pipeline *p;
225 struct rte_table_action *a;
226 } table[RTE_PIPELINE_TABLE_MAX];
227 struct rte_ring *msgq_req;
228 struct rte_ring *msgq_rsp;
229 uint32_t timer_period_ms;
234 struct rte_pipeline *p;
239 struct thread_msg_rsp {
246 static struct thread_msg_req *
247 thread_msg_alloc(void)
249 size_t size = RTE_MAX(sizeof(struct thread_msg_req),
250 sizeof(struct thread_msg_rsp));
252 return calloc(1, size);
256 thread_msg_free(struct thread_msg_rsp *rsp)
261 static struct thread_msg_rsp *
262 thread_msg_send_recv(struct pmd_internals *softnic,
264 struct thread_msg_req *req)
266 struct softnic_thread *t = &softnic->thread[thread_id];
267 struct rte_ring *msgq_req = t->msgq_req;
268 struct rte_ring *msgq_rsp = t->msgq_rsp;
269 struct thread_msg_rsp *rsp;
274 status = rte_ring_sp_enqueue(msgq_req, req);
275 } while (status == -ENOBUFS);
279 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
280 } while (status != 0);
286 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
288 const char *pipeline_name)
290 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
291 struct thread_msg_req *req;
292 struct thread_msg_rsp *rsp;
293 uint32_t n_pipelines, i;
296 /* Check input params */
297 if (!thread_is_valid(softnic, thread_id) ||
299 (p->n_ports_in == 0) ||
300 (p->n_ports_out == 0) ||
301 (p->n_tables == 0) ||
305 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
306 if (n_pipelines >= THREAD_PIPELINES_MAX)
309 if (softnic->params.sc && (n_pipelines == 0)) {
310 status = thread_sc_service_up(softnic, thread_id);
315 if (!thread_is_running(thread_id)) {
316 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
317 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
319 /* Data plane thread */
320 td->p[td->n_pipelines] = p->p;
323 for (i = 0; i < p->n_tables; i++)
324 tdp->table_data[i].a =
326 tdp->n_tables = p->n_tables;
328 tdp->msgq_req = p->msgq_req;
329 tdp->msgq_rsp = p->msgq_rsp;
330 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
331 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
336 p->thread_id = thread_id;
342 /* Allocate request */
343 req = thread_msg_alloc();
348 req->type = THREAD_REQ_PIPELINE_ENABLE;
349 req->pipeline_enable.p = p->p;
350 for (i = 0; i < p->n_tables; i++)
351 req->pipeline_enable.table[i].a =
353 req->pipeline_enable.msgq_req = p->msgq_req;
354 req->pipeline_enable.msgq_rsp = p->msgq_rsp;
355 req->pipeline_enable.timer_period_ms = p->timer_period_ms;
356 req->pipeline_enable.n_tables = p->n_tables;
358 /* Send request and wait for response */
359 rsp = thread_msg_send_recv(softnic, thread_id, req);
362 status = rsp->status;
365 thread_msg_free(rsp);
367 /* Request completion */
371 p->thread_id = thread_id;
378 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
380 const char *pipeline_name)
382 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
383 struct thread_msg_req *req;
384 struct thread_msg_rsp *rsp;
385 uint32_t n_pipelines;
388 /* Check input params */
389 if (!thread_is_valid(softnic, thread_id) ||
391 (p->enabled && (p->thread_id != thread_id)))
397 if (!thread_is_running(thread_id)) {
398 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
401 for (i = 0; i < td->n_pipelines; i++) {
402 struct pipeline_data *tdp = &td->pipeline_data[i];
407 /* Data plane thread */
408 if (i < td->n_pipelines - 1) {
409 struct rte_pipeline *pipeline_last =
410 td->p[td->n_pipelines - 1];
411 struct pipeline_data *tdp_last =
412 &td->pipeline_data[td->n_pipelines - 1];
414 td->p[i] = pipeline_last;
415 memcpy(tdp, tdp_last, sizeof(*tdp));
426 if (softnic->params.sc && (td->n_pipelines == 0))
427 thread_sc_service_down(softnic, thread_id);
432 /* Allocate request */
433 req = thread_msg_alloc();
438 req->type = THREAD_REQ_PIPELINE_DISABLE;
439 req->pipeline_disable.p = p->p;
441 /* Send request and wait for response */
442 rsp = thread_msg_send_recv(softnic, thread_id, req);
445 status = rsp->status;
448 thread_msg_free(rsp);
450 /* Request completion */
456 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
457 if (softnic->params.sc && (n_pipelines == 0))
458 thread_sc_service_down(softnic, thread_id);
464 * Data plane threads: message handling
466 static inline struct thread_msg_req *
467 thread_msg_recv(struct rte_ring *msgq_req)
469 struct thread_msg_req *req;
471 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
480 thread_msg_send(struct rte_ring *msgq_rsp,
481 struct thread_msg_rsp *rsp)
486 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
487 } while (status == -ENOBUFS);
490 static struct thread_msg_rsp *
491 thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
492 struct thread_msg_req *req)
494 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
495 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
499 t->p[t->n_pipelines] = req->pipeline_enable.p;
501 p->p = req->pipeline_enable.p;
502 for (i = 0; i < req->pipeline_enable.n_tables; i++)
504 req->pipeline_enable.table[i].a;
506 p->n_tables = req->pipeline_enable.n_tables;
508 p->msgq_req = req->pipeline_enable.msgq_req;
509 p->msgq_rsp = req->pipeline_enable.msgq_rsp;
511 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
512 p->time_next = rte_get_tsc_cycles() + p->timer_period;
521 static struct thread_msg_rsp *
522 thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
523 struct thread_msg_req *req)
525 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
526 uint32_t n_pipelines = t->n_pipelines;
527 struct rte_pipeline *pipeline = req->pipeline_disable.p;
531 for (i = 0; i < n_pipelines; i++) {
532 struct pipeline_data *p = &t->pipeline_data[i];
534 if (p->p != pipeline)
537 if (i < n_pipelines - 1) {
538 struct rte_pipeline *pipeline_last =
539 t->p[n_pipelines - 1];
540 struct pipeline_data *p_last =
541 &t->pipeline_data[n_pipelines - 1];
543 t->p[i] = pipeline_last;
544 memcpy(p, p_last, sizeof(*p));
553 /* should not get here */
559 thread_msg_handle(struct softnic_thread_data *t)
562 struct thread_msg_req *req;
563 struct thread_msg_rsp *rsp;
565 req = thread_msg_recv(t->msgq_req);
570 case THREAD_REQ_PIPELINE_ENABLE:
571 rsp = thread_msg_handle_pipeline_enable(t, req);
574 case THREAD_REQ_PIPELINE_DISABLE:
575 rsp = thread_msg_handle_pipeline_disable(t, req);
579 rsp = (struct thread_msg_rsp *)req;
583 thread_msg_send(t->msgq_rsp, rsp);
588 * Main thread & data plane threads: message passing
590 enum pipeline_req_type {
592 PIPELINE_REQ_PORT_IN_STATS_READ,
593 PIPELINE_REQ_PORT_IN_ENABLE,
594 PIPELINE_REQ_PORT_IN_DISABLE,
597 PIPELINE_REQ_PORT_OUT_STATS_READ,
600 PIPELINE_REQ_TABLE_STATS_READ,
601 PIPELINE_REQ_TABLE_RULE_ADD,
602 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
603 PIPELINE_REQ_TABLE_RULE_ADD_BULK,
604 PIPELINE_REQ_TABLE_RULE_DELETE,
605 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
606 PIPELINE_REQ_TABLE_RULE_STATS_READ,
607 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
608 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
609 PIPELINE_REQ_TABLE_RULE_MTR_READ,
610 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
611 PIPELINE_REQ_TABLE_RULE_TTL_READ,
615 struct pipeline_msg_req_port_in_stats_read {
619 struct pipeline_msg_req_port_out_stats_read {
623 struct pipeline_msg_req_table_stats_read {
627 struct pipeline_msg_req_table_rule_add {
628 struct softnic_table_rule_match match;
629 struct softnic_table_rule_action action;
632 struct pipeline_msg_req_table_rule_add_default {
633 struct softnic_table_rule_action action;
636 struct pipeline_msg_req_table_rule_add_bulk {
637 struct softnic_table_rule_match *match;
638 struct softnic_table_rule_action *action;
644 struct pipeline_msg_req_table_rule_delete {
645 struct softnic_table_rule_match match;
648 struct pipeline_msg_req_table_rule_stats_read {
653 struct pipeline_msg_req_table_mtr_profile_add {
654 uint32_t meter_profile_id;
655 struct rte_table_action_meter_profile profile;
658 struct pipeline_msg_req_table_mtr_profile_delete {
659 uint32_t meter_profile_id;
662 struct pipeline_msg_req_table_rule_mtr_read {
668 struct pipeline_msg_req_table_dscp_table_update {
670 struct rte_table_action_dscp_table dscp_table;
673 struct pipeline_msg_req_table_rule_ttl_read {
678 struct pipeline_msg_req {
679 enum pipeline_req_type type;
680 uint32_t id; /* Port IN, port OUT or table ID */
684 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
685 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
686 struct pipeline_msg_req_table_stats_read table_stats_read;
687 struct pipeline_msg_req_table_rule_add table_rule_add;
688 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
689 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
690 struct pipeline_msg_req_table_rule_delete table_rule_delete;
691 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
692 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
693 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
694 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
695 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
696 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
700 struct pipeline_msg_rsp_port_in_stats_read {
701 struct rte_pipeline_port_in_stats stats;
704 struct pipeline_msg_rsp_port_out_stats_read {
705 struct rte_pipeline_port_out_stats stats;
708 struct pipeline_msg_rsp_table_stats_read {
709 struct rte_pipeline_table_stats stats;
712 struct pipeline_msg_rsp_table_rule_add {
716 struct pipeline_msg_rsp_table_rule_add_default {
720 struct pipeline_msg_rsp_table_rule_add_bulk {
724 struct pipeline_msg_rsp_table_rule_stats_read {
725 struct rte_table_action_stats_counters stats;
728 struct pipeline_msg_rsp_table_rule_mtr_read {
729 struct rte_table_action_mtr_counters stats;
732 struct pipeline_msg_rsp_table_rule_ttl_read {
733 struct rte_table_action_ttl_counters stats;
736 struct pipeline_msg_rsp {
741 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
742 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
743 struct pipeline_msg_rsp_table_stats_read table_stats_read;
744 struct pipeline_msg_rsp_table_rule_add table_rule_add;
745 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
746 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
747 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
748 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
749 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
756 static struct pipeline_msg_req *
757 pipeline_msg_alloc(void)
759 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
760 sizeof(struct pipeline_msg_rsp));
762 return calloc(1, size);
766 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
771 static struct pipeline_msg_rsp *
772 pipeline_msg_send_recv(struct pipeline *p,
773 struct pipeline_msg_req *req)
775 struct rte_ring *msgq_req = p->msgq_req;
776 struct rte_ring *msgq_rsp = p->msgq_rsp;
777 struct pipeline_msg_rsp *rsp;
782 status = rte_ring_sp_enqueue(msgq_req, req);
783 } while (status == -ENOBUFS);
787 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
788 } while (status != 0);
794 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
795 const char *pipeline_name,
797 struct rte_pipeline_port_in_stats *stats,
801 struct pipeline_msg_req *req;
802 struct pipeline_msg_rsp *rsp;
805 /* Check input params */
806 if (pipeline_name == NULL ||
810 p = softnic_pipeline_find(softnic, pipeline_name);
812 port_id >= p->n_ports_in)
815 if (!pipeline_is_running(p)) {
816 status = rte_pipeline_port_in_stats_read(p->p,
824 /* Allocate request */
825 req = pipeline_msg_alloc();
830 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
832 req->port_in_stats_read.clear = clear;
834 /* Send request and wait for response */
835 rsp = pipeline_msg_send_recv(p, req);
838 status = rsp->status;
840 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
843 pipeline_msg_free(rsp);
849 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
850 const char *pipeline_name,
854 struct pipeline_msg_req *req;
855 struct pipeline_msg_rsp *rsp;
858 /* Check input params */
859 if (pipeline_name == NULL)
862 p = softnic_pipeline_find(softnic, pipeline_name);
864 port_id >= p->n_ports_in)
867 if (!pipeline_is_running(p)) {
868 status = rte_pipeline_port_in_enable(p->p, port_id);
872 /* Allocate request */
873 req = pipeline_msg_alloc();
878 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
881 /* Send request and wait for response */
882 rsp = pipeline_msg_send_recv(p, req);
885 status = rsp->status;
888 pipeline_msg_free(rsp);
894 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
895 const char *pipeline_name,
899 struct pipeline_msg_req *req;
900 struct pipeline_msg_rsp *rsp;
903 /* Check input params */
904 if (pipeline_name == NULL)
907 p = softnic_pipeline_find(softnic, pipeline_name);
909 port_id >= p->n_ports_in)
912 if (!pipeline_is_running(p)) {
913 status = rte_pipeline_port_in_disable(p->p, port_id);
917 /* Allocate request */
918 req = pipeline_msg_alloc();
923 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
926 /* Send request and wait for response */
927 rsp = pipeline_msg_send_recv(p, req);
930 status = rsp->status;
933 pipeline_msg_free(rsp);
939 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
940 const char *pipeline_name,
942 struct rte_pipeline_port_out_stats *stats,
946 struct pipeline_msg_req *req;
947 struct pipeline_msg_rsp *rsp;
950 /* Check input params */
951 if (pipeline_name == NULL ||
955 p = softnic_pipeline_find(softnic, pipeline_name);
957 port_id >= p->n_ports_out)
960 if (!pipeline_is_running(p)) {
961 status = rte_pipeline_port_out_stats_read(p->p,
969 /* Allocate request */
970 req = pipeline_msg_alloc();
975 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
977 req->port_out_stats_read.clear = clear;
979 /* Send request and wait for response */
980 rsp = pipeline_msg_send_recv(p, req);
983 status = rsp->status;
985 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
988 pipeline_msg_free(rsp);
994 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
995 const char *pipeline_name,
997 struct rte_pipeline_table_stats *stats,
1001 struct pipeline_msg_req *req;
1002 struct pipeline_msg_rsp *rsp;
1005 /* Check input params */
1006 if (pipeline_name == NULL ||
1010 p = softnic_pipeline_find(softnic, pipeline_name);
1012 table_id >= p->n_tables)
1015 if (!pipeline_is_running(p)) {
1016 status = rte_pipeline_table_stats_read(p->p,
1024 /* Allocate request */
1025 req = pipeline_msg_alloc();
1030 req->type = PIPELINE_REQ_TABLE_STATS_READ;
1032 req->table_stats_read.clear = clear;
1034 /* Send request and wait for response */
1035 rsp = pipeline_msg_send_recv(p, req);
1038 status = rsp->status;
1040 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
1043 pipeline_msg_free(rsp);
1049 match_check(struct softnic_table_rule_match *match,
1053 struct softnic_table *table;
1055 if (match == NULL ||
1057 table_id >= p->n_tables)
1060 table = &p->table[table_id];
1061 if (match->match_type != table->params.match_type)
1064 switch (match->match_type) {
1067 struct softnic_table_acl_params *t = &table->params.match.acl;
1068 struct softnic_table_rule_match_acl *r = &match->match.acl;
1070 if ((r->ip_version && (t->ip_version == 0)) ||
1071 ((r->ip_version == 0) && t->ip_version))
1074 if (r->ip_version) {
1075 if (r->sa_depth > 32 ||
1079 if (r->sa_depth > 128 ||
1094 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1095 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1097 if ((r->ip_version && (t->key_size != 4)) ||
1098 ((r->ip_version == 0) && (t->key_size != 16)))
1101 if (r->ip_version) {
1120 action_check(struct softnic_table_rule_action *action,
1124 struct softnic_table_action_profile *ap;
1126 if (action == NULL ||
1128 table_id >= p->n_tables)
1131 ap = p->table[table_id].ap;
1132 if (action->action_mask != ap->params.action_mask)
1135 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1136 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1137 action->fwd.id >= p->n_ports_out)
1140 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1141 action->fwd.id >= p->n_tables)
1145 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1146 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1147 uint32_t tc_mask1 = action->mtr.tc_mask;
1149 if (tc_mask1 != tc_mask0)
1153 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1154 uint32_t n_subports_per_port =
1155 ap->params.tm.n_subports_per_port;
1156 uint32_t n_pipes_per_subport =
1157 ap->params.tm.n_pipes_per_subport;
1158 uint32_t subport_id = action->tm.subport_id;
1159 uint32_t pipe_id = action->tm.pipe_id;
1161 if (subport_id >= n_subports_per_port ||
1162 pipe_id >= n_pipes_per_subport)
1166 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1167 uint64_t encap_mask = ap->params.encap.encap_mask;
1168 enum rte_table_action_encap_type type = action->encap.type;
1170 if ((encap_mask & (1LLU << type)) == 0)
1174 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1175 int ip_version0 = ap->params.common.ip_version;
1176 int ip_version1 = action->nat.ip_version;
1178 if ((ip_version1 && (ip_version0 == 0)) ||
1179 ((ip_version1 == 0) && ip_version0))
1187 action_default_check(struct softnic_table_rule_action *action,
1191 if (action == NULL ||
1192 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1194 table_id >= p->n_tables)
1197 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1198 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1199 action->fwd.id >= p->n_ports_out)
1202 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1203 action->fwd.id >= p->n_tables)
1210 union table_rule_match_low_level {
1211 struct rte_table_acl_rule_add_params acl_add;
1212 struct rte_table_acl_rule_delete_params acl_delete;
1213 struct rte_table_array_key array;
1214 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1215 struct rte_table_lpm_key lpm_ipv4;
1216 struct rte_table_lpm_ipv6_key lpm_ipv6;
1220 match_convert(struct softnic_table_rule_match *mh,
1221 union table_rule_match_low_level *ml,
1225 action_convert(struct rte_table_action *a,
1226 struct softnic_table_rule_action *action,
1227 struct rte_pipeline_table_entry *data);
1230 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1231 const char *pipeline_name,
1233 struct softnic_table_rule_match *match,
1234 struct softnic_table_rule_action *action,
1238 struct pipeline_msg_req *req;
1239 struct pipeline_msg_rsp *rsp;
1242 /* Check input params */
1243 if (pipeline_name == NULL ||
1249 p = softnic_pipeline_find(softnic, pipeline_name);
1251 table_id >= p->n_tables ||
1252 match_check(match, p, table_id) ||
1253 action_check(action, p, table_id))
1256 if (!pipeline_is_running(p)) {
1257 struct rte_table_action *a = p->table[table_id].a;
1258 union table_rule_match_low_level match_ll;
1259 struct rte_pipeline_table_entry *data_in, *data_out;
1263 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1267 /* Table match-action rule conversion */
1268 data_in = (struct rte_pipeline_table_entry *)buffer;
1270 status = match_convert(match, &match_ll, 1);
1276 status = action_convert(a, action, data_in);
1282 /* Add rule (match, action) to table */
1283 status = rte_pipeline_table_entry_add(p->p,
1294 /* Write Response */
1301 /* Allocate request */
1302 req = pipeline_msg_alloc();
1307 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1309 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1310 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1312 /* Send request and wait for response */
1313 rsp = pipeline_msg_send_recv(p, req);
1316 status = rsp->status;
1318 *data = rsp->table_rule_add.data;
1321 pipeline_msg_free(rsp);
1327 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1328 const char *pipeline_name,
1330 struct softnic_table_rule_action *action,
1334 struct pipeline_msg_req *req;
1335 struct pipeline_msg_rsp *rsp;
1338 /* Check input params */
1339 if (pipeline_name == NULL ||
1344 p = softnic_pipeline_find(softnic, pipeline_name);
1346 table_id >= p->n_tables ||
1347 action_default_check(action, p, table_id))
1350 if (!pipeline_is_running(p)) {
1351 struct rte_pipeline_table_entry *data_in, *data_out;
1354 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1359 data_in = (struct rte_pipeline_table_entry *)buffer;
1361 data_in->action = action->fwd.action;
1362 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1363 data_in->port_id = action->fwd.id;
1364 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1365 data_in->table_id = action->fwd.id;
1367 /* Add default rule to table */
1368 status = rte_pipeline_table_default_entry_add(p->p,
1377 /* Write Response */
1384 /* Allocate request */
1385 req = pipeline_msg_alloc();
1390 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1392 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1394 /* Send request and wait for response */
1395 rsp = pipeline_msg_send_recv(p, req);
1398 status = rsp->status;
1400 *data = rsp->table_rule_add_default.data;
1403 pipeline_msg_free(rsp);
1409 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1410 const char *pipeline_name,
1412 struct softnic_table_rule_match *match,
1413 struct softnic_table_rule_action *action,
1418 struct pipeline_msg_req *req;
1419 struct pipeline_msg_rsp *rsp;
1423 /* Check input params */
1424 if (pipeline_name == NULL ||
1432 p = softnic_pipeline_find(softnic, pipeline_name);
1434 table_id >= p->n_tables)
1437 for (i = 0; i < *n_rules; i++)
1438 if (match_check(match, p, table_id) ||
1439 action_check(action, p, table_id))
1442 if (!pipeline_is_running(p)) {
1443 struct rte_table_action *a = p->table[table_id].a;
1444 union table_rule_match_low_level *match_ll;
1446 void **match_ll_ptr;
1447 struct rte_pipeline_table_entry **action_ll_ptr;
1448 struct rte_pipeline_table_entry **entries_ptr =
1449 (struct rte_pipeline_table_entry **)data;
1451 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1454 /* Memory allocation */
1455 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1456 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1457 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1459 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1460 found = calloc(*n_rules, sizeof(int));
1462 if (match_ll == NULL ||
1463 action_ll == NULL ||
1464 match_ll_ptr == NULL ||
1465 action_ll_ptr == NULL ||
1469 for (i = 0; i < *n_rules; i++) {
1470 match_ll_ptr[i] = (void *)&match_ll[i];
1472 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1475 /* Rule match conversion */
1476 for (i = 0; i < *n_rules; i++) {
1477 status = match_convert(&match[i], match_ll_ptr[i], 1);
1482 /* Rule action conversion */
1483 for (i = 0; i < *n_rules; i++) {
1484 status = action_convert(a, &action[i], action_ll_ptr[i]);
1489 /* Add rule (match, action) to table */
1491 status = rte_pipeline_table_entry_add_bulk(p->p,
1501 for (i = 0; i < *n_rules; i++) {
1502 status = rte_pipeline_table_entry_add(p->p,
1517 free(action_ll_ptr);
1526 free(action_ll_ptr);
1535 /* Allocate request */
1536 req = pipeline_msg_alloc();
1541 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1543 req->table_rule_add_bulk.match = match;
1544 req->table_rule_add_bulk.action = action;
1545 req->table_rule_add_bulk.data = data;
1546 req->table_rule_add_bulk.n_rules = *n_rules;
1547 req->table_rule_add_bulk.bulk =
1548 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1550 /* Send request and wait for response */
1551 rsp = pipeline_msg_send_recv(p, req);
1554 status = rsp->status;
1556 *n_rules = rsp->table_rule_add_bulk.n_rules;
1559 pipeline_msg_free(rsp);
1565 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1566 const char *pipeline_name,
1568 struct softnic_table_rule_match *match)
1571 struct pipeline_msg_req *req;
1572 struct pipeline_msg_rsp *rsp;
1575 /* Check input params */
1576 if (pipeline_name == NULL ||
1580 p = softnic_pipeline_find(softnic, pipeline_name);
1582 table_id >= p->n_tables ||
1583 match_check(match, p, table_id))
1586 if (!pipeline_is_running(p)) {
1587 union table_rule_match_low_level match_ll;
1590 status = match_convert(match, &match_ll, 0);
1594 status = rte_pipeline_table_entry_delete(p->p,
1603 /* Allocate request */
1604 req = pipeline_msg_alloc();
1609 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1611 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1613 /* Send request and wait for response */
1614 rsp = pipeline_msg_send_recv(p, req);
1617 status = rsp->status;
1620 pipeline_msg_free(rsp);
1626 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1627 const char *pipeline_name,
1631 struct pipeline_msg_req *req;
1632 struct pipeline_msg_rsp *rsp;
1635 /* Check input params */
1636 if (pipeline_name == NULL)
1639 p = softnic_pipeline_find(softnic, pipeline_name);
1641 table_id >= p->n_tables)
1644 if (!pipeline_is_running(p)) {
1645 status = rte_pipeline_table_default_entry_delete(p->p,
1652 /* Allocate request */
1653 req = pipeline_msg_alloc();
1658 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1661 /* Send request and wait for response */
1662 rsp = pipeline_msg_send_recv(p, req);
1665 status = rsp->status;
1668 pipeline_msg_free(rsp);
1674 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1675 const char *pipeline_name,
1678 struct rte_table_action_stats_counters *stats,
1682 struct pipeline_msg_req *req;
1683 struct pipeline_msg_rsp *rsp;
1686 /* Check input params */
1687 if (pipeline_name == NULL ||
1692 p = softnic_pipeline_find(softnic, pipeline_name);
1694 table_id >= p->n_tables)
1697 if (!pipeline_is_running(p)) {
1698 struct rte_table_action *a = p->table[table_id].a;
1700 status = rte_table_action_stats_read(a,
1708 /* Allocate request */
1709 req = pipeline_msg_alloc();
1714 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1716 req->table_rule_stats_read.data = data;
1717 req->table_rule_stats_read.clear = clear;
1719 /* Send request and wait for response */
1720 rsp = pipeline_msg_send_recv(p, req);
1723 status = rsp->status;
1725 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1728 pipeline_msg_free(rsp);
1734 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1735 const char *pipeline_name,
1737 uint32_t meter_profile_id,
1738 struct rte_table_action_meter_profile *profile)
1741 struct pipeline_msg_req *req;
1742 struct pipeline_msg_rsp *rsp;
1743 struct softnic_table *table;
1744 struct softnic_table_meter_profile *mp;
1747 /* Check input params */
1748 if (pipeline_name == NULL ||
1752 p = softnic_pipeline_find(softnic, pipeline_name);
1754 table_id >= p->n_tables)
1757 table = &p->table[table_id];
1758 mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
1762 /* Resource Allocation */
1763 mp = calloc(1, sizeof(struct softnic_table_meter_profile));
1767 mp->meter_profile_id = meter_profile_id;
1768 memcpy(&mp->profile, profile, sizeof(mp->profile));
1770 if (!pipeline_is_running(p)) {
1771 status = rte_table_action_meter_profile_add(table->a,
1779 /* Add profile to the table. */
1780 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1785 /* Allocate request */
1786 req = pipeline_msg_alloc();
1793 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1795 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1796 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1798 /* Send request and wait for response */
1799 rsp = pipeline_msg_send_recv(p, req);
1802 status = rsp->status;
1804 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1809 pipeline_msg_free(rsp);
1815 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1816 const char *pipeline_name,
1818 uint32_t meter_profile_id)
1821 struct pipeline_msg_req *req;
1822 struct pipeline_msg_rsp *rsp;
1825 /* Check input params */
1826 if (pipeline_name == NULL)
1829 p = softnic_pipeline_find(softnic, pipeline_name);
1831 table_id >= p->n_tables)
1834 if (!pipeline_is_running(p)) {
1835 struct rte_table_action *a = p->table[table_id].a;
1837 status = rte_table_action_meter_profile_delete(a,
1843 /* Allocate request */
1844 req = pipeline_msg_alloc();
1849 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1851 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1853 /* Send request and wait for response */
1854 rsp = pipeline_msg_send_recv(p, req);
1857 status = rsp->status;
1860 pipeline_msg_free(rsp);
1866 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1867 const char *pipeline_name,
1871 struct rte_table_action_mtr_counters *stats,
1875 struct pipeline_msg_req *req;
1876 struct pipeline_msg_rsp *rsp;
1879 /* Check input params */
1880 if (pipeline_name == NULL ||
1885 p = softnic_pipeline_find(softnic, pipeline_name);
1887 table_id >= p->n_tables)
1890 if (!pipeline_is_running(p)) {
1891 struct rte_table_action *a = p->table[table_id].a;
1893 status = rte_table_action_meter_read(a,
1902 /* Allocate request */
1903 req = pipeline_msg_alloc();
1908 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1910 req->table_rule_mtr_read.data = data;
1911 req->table_rule_mtr_read.tc_mask = tc_mask;
1912 req->table_rule_mtr_read.clear = clear;
1914 /* Send request and wait for response */
1915 rsp = pipeline_msg_send_recv(p, req);
1918 status = rsp->status;
1920 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1923 pipeline_msg_free(rsp);
1929 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1930 const char *pipeline_name,
1933 struct rte_table_action_dscp_table *dscp_table)
1936 struct pipeline_msg_req *req;
1937 struct pipeline_msg_rsp *rsp;
1940 /* Check input params */
1941 if (pipeline_name == NULL ||
1945 p = softnic_pipeline_find(softnic, pipeline_name);
1947 table_id >= p->n_tables)
1950 if (!pipeline_is_running(p)) {
1951 struct rte_table_action *a = p->table[table_id].a;
1953 status = rte_table_action_dscp_table_update(a,
1957 /* Update table dscp table */
1959 memcpy(&p->table[table_id].dscp_table, dscp_table,
1960 sizeof(p->table[table_id].dscp_table));
1965 /* Allocate request */
1966 req = pipeline_msg_alloc();
1971 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
1973 req->table_dscp_table_update.dscp_mask = dscp_mask;
1974 memcpy(&req->table_dscp_table_update.dscp_table,
1975 dscp_table, sizeof(*dscp_table));
1977 /* Send request and wait for response */
1978 rsp = pipeline_msg_send_recv(p, req);
1981 status = rsp->status;
1983 /* Update table dscp table */
1985 memcpy(&p->table[table_id].dscp_table, dscp_table,
1986 sizeof(p->table[table_id].dscp_table));
1989 pipeline_msg_free(rsp);
1995 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
1996 const char *pipeline_name,
1999 struct rte_table_action_ttl_counters *stats,
2003 struct pipeline_msg_req *req;
2004 struct pipeline_msg_rsp *rsp;
2007 /* Check input params */
2008 if (pipeline_name == NULL ||
2013 p = softnic_pipeline_find(softnic, pipeline_name);
2015 table_id >= p->n_tables)
2018 if (!pipeline_is_running(p)) {
2019 struct rte_table_action *a = p->table[table_id].a;
2021 status = rte_table_action_ttl_read(a,
2029 /* Allocate request */
2030 req = pipeline_msg_alloc();
2035 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
2037 req->table_rule_ttl_read.data = data;
2038 req->table_rule_ttl_read.clear = clear;
2040 /* Send request and wait for response */
2041 rsp = pipeline_msg_send_recv(p, req);
2044 status = rsp->status;
2046 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2049 pipeline_msg_free(rsp);
2055 * Data plane threads: message handling
2057 static inline struct pipeline_msg_req *
2058 pipeline_msg_recv(struct rte_ring *msgq_req)
2060 struct pipeline_msg_req *req;
2062 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2071 pipeline_msg_send(struct rte_ring *msgq_rsp,
2072 struct pipeline_msg_rsp *rsp)
2077 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2078 } while (status == -ENOBUFS);
2081 static struct pipeline_msg_rsp *
2082 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2083 struct pipeline_msg_req *req)
2085 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2086 uint32_t port_id = req->id;
2087 int clear = req->port_in_stats_read.clear;
2089 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2091 &rsp->port_in_stats_read.stats,
2097 static struct pipeline_msg_rsp *
2098 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2099 struct pipeline_msg_req *req)
2101 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2102 uint32_t port_id = req->id;
2104 rsp->status = rte_pipeline_port_in_enable(p->p,
2110 static struct pipeline_msg_rsp *
2111 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2112 struct pipeline_msg_req *req)
2114 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2115 uint32_t port_id = req->id;
2117 rsp->status = rte_pipeline_port_in_disable(p->p,
2123 static struct pipeline_msg_rsp *
2124 pipeline_msg_handle_port_out_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_out_stats_read.clear;
2131 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2133 &rsp->port_out_stats_read.stats,
2139 static struct pipeline_msg_rsp *
2140 pipeline_msg_handle_table_stats_read(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;
2145 int clear = req->table_stats_read.clear;
2147 rsp->status = rte_pipeline_table_stats_read(p->p,
2149 &rsp->table_stats_read.stats,
2156 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2161 switch (depth / 32) {
2171 depth32[1] = depth - 32;
2179 depth32[2] = depth - 64;
2187 depth32[3] = depth - 96;
2203 match_convert(struct softnic_table_rule_match *mh,
2204 union table_rule_match_low_level *ml,
2207 memset(ml, 0, sizeof(*ml));
2209 switch (mh->match_type) {
2211 if (mh->match.acl.ip_version)
2213 ml->acl_add.field_value[0].value.u8 =
2214 mh->match.acl.proto;
2215 ml->acl_add.field_value[0].mask_range.u8 =
2216 mh->match.acl.proto_mask;
2218 ml->acl_add.field_value[1].value.u32 =
2219 mh->match.acl.ipv4.sa;
2220 ml->acl_add.field_value[1].mask_range.u32 =
2221 mh->match.acl.sa_depth;
2223 ml->acl_add.field_value[2].value.u32 =
2224 mh->match.acl.ipv4.da;
2225 ml->acl_add.field_value[2].mask_range.u32 =
2226 mh->match.acl.da_depth;
2228 ml->acl_add.field_value[3].value.u16 =
2230 ml->acl_add.field_value[3].mask_range.u16 =
2233 ml->acl_add.field_value[4].value.u16 =
2235 ml->acl_add.field_value[4].mask_range.u16 =
2238 ml->acl_add.priority =
2239 (int32_t)mh->match.acl.priority;
2241 ml->acl_delete.field_value[0].value.u8 =
2242 mh->match.acl.proto;
2243 ml->acl_delete.field_value[0].mask_range.u8 =
2244 mh->match.acl.proto_mask;
2246 ml->acl_delete.field_value[1].value.u32 =
2247 mh->match.acl.ipv4.sa;
2248 ml->acl_delete.field_value[1].mask_range.u32 =
2249 mh->match.acl.sa_depth;
2251 ml->acl_delete.field_value[2].value.u32 =
2252 mh->match.acl.ipv4.da;
2253 ml->acl_delete.field_value[2].mask_range.u32 =
2254 mh->match.acl.da_depth;
2256 ml->acl_delete.field_value[3].value.u16 =
2258 ml->acl_delete.field_value[3].mask_range.u16 =
2261 ml->acl_delete.field_value[4].value.u16 =
2263 ml->acl_delete.field_value[4].mask_range.u16 =
2269 (uint32_t *)mh->match.acl.ipv6.sa;
2271 (uint32_t *)mh->match.acl.ipv6.da;
2272 uint32_t sa32_depth[4], da32_depth[4];
2275 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2280 status = match_convert_ipv6_depth(
2281 mh->match.acl.da_depth,
2286 ml->acl_add.field_value[0].value.u8 =
2287 mh->match.acl.proto;
2288 ml->acl_add.field_value[0].mask_range.u8 =
2289 mh->match.acl.proto_mask;
2291 ml->acl_add.field_value[1].value.u32 =
2292 rte_be_to_cpu_32(sa32[0]);
2293 ml->acl_add.field_value[1].mask_range.u32 =
2295 ml->acl_add.field_value[2].value.u32 =
2296 rte_be_to_cpu_32(sa32[1]);
2297 ml->acl_add.field_value[2].mask_range.u32 =
2299 ml->acl_add.field_value[3].value.u32 =
2300 rte_be_to_cpu_32(sa32[2]);
2301 ml->acl_add.field_value[3].mask_range.u32 =
2303 ml->acl_add.field_value[4].value.u32 =
2304 rte_be_to_cpu_32(sa32[3]);
2305 ml->acl_add.field_value[4].mask_range.u32 =
2308 ml->acl_add.field_value[5].value.u32 =
2309 rte_be_to_cpu_32(da32[0]);
2310 ml->acl_add.field_value[5].mask_range.u32 =
2312 ml->acl_add.field_value[6].value.u32 =
2313 rte_be_to_cpu_32(da32[1]);
2314 ml->acl_add.field_value[6].mask_range.u32 =
2316 ml->acl_add.field_value[7].value.u32 =
2317 rte_be_to_cpu_32(da32[2]);
2318 ml->acl_add.field_value[7].mask_range.u32 =
2320 ml->acl_add.field_value[8].value.u32 =
2321 rte_be_to_cpu_32(da32[3]);
2322 ml->acl_add.field_value[8].mask_range.u32 =
2325 ml->acl_add.field_value[9].value.u16 =
2327 ml->acl_add.field_value[9].mask_range.u16 =
2330 ml->acl_add.field_value[10].value.u16 =
2332 ml->acl_add.field_value[10].mask_range.u16 =
2335 ml->acl_add.priority =
2336 (int32_t)mh->match.acl.priority;
2339 (uint32_t *)mh->match.acl.ipv6.sa;
2341 (uint32_t *)mh->match.acl.ipv6.da;
2342 uint32_t sa32_depth[4], da32_depth[4];
2345 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2350 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2355 ml->acl_delete.field_value[0].value.u8 =
2356 mh->match.acl.proto;
2357 ml->acl_delete.field_value[0].mask_range.u8 =
2358 mh->match.acl.proto_mask;
2360 ml->acl_delete.field_value[1].value.u32 =
2361 rte_be_to_cpu_32(sa32[0]);
2362 ml->acl_delete.field_value[1].mask_range.u32 =
2364 ml->acl_delete.field_value[2].value.u32 =
2365 rte_be_to_cpu_32(sa32[1]);
2366 ml->acl_delete.field_value[2].mask_range.u32 =
2368 ml->acl_delete.field_value[3].value.u32 =
2369 rte_be_to_cpu_32(sa32[2]);
2370 ml->acl_delete.field_value[3].mask_range.u32 =
2372 ml->acl_delete.field_value[4].value.u32 =
2373 rte_be_to_cpu_32(sa32[3]);
2374 ml->acl_delete.field_value[4].mask_range.u32 =
2377 ml->acl_delete.field_value[5].value.u32 =
2378 rte_be_to_cpu_32(da32[0]);
2379 ml->acl_delete.field_value[5].mask_range.u32 =
2381 ml->acl_delete.field_value[6].value.u32 =
2382 rte_be_to_cpu_32(da32[1]);
2383 ml->acl_delete.field_value[6].mask_range.u32 =
2385 ml->acl_delete.field_value[7].value.u32 =
2386 rte_be_to_cpu_32(da32[2]);
2387 ml->acl_delete.field_value[7].mask_range.u32 =
2389 ml->acl_delete.field_value[8].value.u32 =
2390 rte_be_to_cpu_32(da32[3]);
2391 ml->acl_delete.field_value[8].mask_range.u32 =
2394 ml->acl_delete.field_value[9].value.u16 =
2396 ml->acl_delete.field_value[9].mask_range.u16 =
2399 ml->acl_delete.field_value[10].value.u16 =
2401 ml->acl_delete.field_value[10].mask_range.u16 =
2407 ml->array.pos = mh->match.array.pos;
2411 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2415 if (mh->match.lpm.ip_version) {
2416 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2417 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2419 memcpy(ml->lpm_ipv6.ip,
2420 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2421 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2432 action_convert(struct rte_table_action *a,
2433 struct softnic_table_rule_action *action,
2434 struct rte_pipeline_table_entry *data)
2439 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2440 status = rte_table_action_apply(a,
2442 RTE_TABLE_ACTION_FWD,
2449 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2450 status = rte_table_action_apply(a,
2452 RTE_TABLE_ACTION_LB,
2459 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2460 status = rte_table_action_apply(a,
2462 RTE_TABLE_ACTION_MTR,
2469 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2470 status = rte_table_action_apply(a,
2472 RTE_TABLE_ACTION_TM,
2479 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2480 status = rte_table_action_apply(a,
2482 RTE_TABLE_ACTION_ENCAP,
2489 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2490 status = rte_table_action_apply(a,
2492 RTE_TABLE_ACTION_NAT,
2499 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2500 status = rte_table_action_apply(a,
2502 RTE_TABLE_ACTION_TTL,
2509 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2510 status = rte_table_action_apply(a,
2512 RTE_TABLE_ACTION_STATS,
2519 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2520 status = rte_table_action_apply(a,
2522 RTE_TABLE_ACTION_TIME,
2529 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2530 status = rte_table_action_apply(a,
2532 RTE_TABLE_ACTION_TAG,
2539 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2540 status = rte_table_action_apply(a,
2542 RTE_TABLE_ACTION_DECAP,
2549 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2550 status = rte_table_action_apply(a,
2552 RTE_TABLE_ACTION_SYM_CRYPTO,
2553 &action->sym_crypto);
2562 static struct pipeline_msg_rsp *
2563 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2564 struct pipeline_msg_req *req)
2566 union table_rule_match_low_level match_ll;
2567 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2568 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2569 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2570 struct rte_pipeline_table_entry *data_in, *data_out;
2571 uint32_t table_id = req->id;
2572 int key_found, status;
2573 struct rte_table_action *a = p->table_data[table_id].a;
2576 memset(p->buffer, 0, sizeof(p->buffer));
2577 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2579 status = match_convert(match, &match_ll, 1);
2585 status = action_convert(a, action, data_in);
2591 status = rte_pipeline_table_entry_add(p->p,
2602 /* Write response */
2604 rsp->table_rule_add.data = data_out;
2609 static struct pipeline_msg_rsp *
2610 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2611 struct pipeline_msg_req *req)
2613 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2614 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2615 struct rte_pipeline_table_entry *data_in, *data_out;
2616 uint32_t table_id = req->id;
2620 memset(p->buffer, 0, sizeof(p->buffer));
2621 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2623 data_in->action = action->fwd.action;
2624 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2625 data_in->port_id = action->fwd.id;
2626 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2627 data_in->table_id = action->fwd.id;
2629 /* Add default rule to table */
2630 status = rte_pipeline_table_default_entry_add(p->p,
2639 /* Write response */
2641 rsp->table_rule_add_default.data = data_out;
2646 static struct pipeline_msg_rsp *
2647 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2648 struct pipeline_msg_req *req)
2650 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2652 uint32_t table_id = req->id;
2653 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2654 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2655 struct rte_pipeline_table_entry **data =
2656 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2657 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2658 uint32_t bulk = req->table_rule_add_bulk.bulk;
2660 struct rte_table_action *a = p->table_data[table_id].a;
2661 union table_rule_match_low_level *match_ll;
2663 void **match_ll_ptr;
2664 struct rte_pipeline_table_entry **action_ll_ptr;
2668 /* Memory allocation */
2669 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2670 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2671 match_ll_ptr = calloc(n_rules, sizeof(void *));
2673 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2674 found = calloc(n_rules, sizeof(int));
2676 if (match_ll == NULL ||
2677 action_ll == NULL ||
2678 match_ll_ptr == NULL ||
2679 action_ll_ptr == NULL ||
2683 for (i = 0; i < n_rules; i++) {
2684 match_ll_ptr[i] = (void *)&match_ll[i];
2686 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2689 /* Rule match conversion */
2690 for (i = 0; i < n_rules; i++) {
2691 status = match_convert(&match[i], match_ll_ptr[i], 1);
2696 /* Rule action conversion */
2697 for (i = 0; i < n_rules; i++) {
2698 status = action_convert(a, &action[i], action_ll_ptr[i]);
2703 /* Add rule (match, action) to table */
2705 status = rte_pipeline_table_entry_add_bulk(p->p,
2715 for (i = 0; i < n_rules; i++) {
2716 status = rte_pipeline_table_entry_add(p->p,
2729 /* Write response */
2731 rsp->table_rule_add_bulk.n_rules = n_rules;
2735 free(action_ll_ptr);
2744 free(action_ll_ptr);
2750 rsp->table_rule_add_bulk.n_rules = 0;
2754 static struct pipeline_msg_rsp *
2755 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2756 struct pipeline_msg_req *req)
2758 union table_rule_match_low_level match_ll;
2759 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2760 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2761 uint32_t table_id = req->id;
2762 int key_found, status;
2764 status = match_convert(match, &match_ll, 0);
2770 rsp->status = rte_pipeline_table_entry_delete(p->p,
2779 static struct pipeline_msg_rsp *
2780 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2781 struct pipeline_msg_req *req)
2783 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2784 uint32_t table_id = req->id;
2786 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2793 static struct pipeline_msg_rsp *
2794 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2795 struct pipeline_msg_req *req)
2797 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2798 uint32_t table_id = req->id;
2799 void *data = req->table_rule_stats_read.data;
2800 int clear = req->table_rule_stats_read.clear;
2801 struct rte_table_action *a = p->table_data[table_id].a;
2803 rsp->status = rte_table_action_stats_read(a,
2805 &rsp->table_rule_stats_read.stats,
2811 static struct pipeline_msg_rsp *
2812 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2813 struct pipeline_msg_req *req)
2815 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2816 uint32_t table_id = req->id;
2817 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2818 struct rte_table_action_meter_profile *profile =
2819 &req->table_mtr_profile_add.profile;
2820 struct rte_table_action *a = p->table_data[table_id].a;
2822 rsp->status = rte_table_action_meter_profile_add(a,
2829 static struct pipeline_msg_rsp *
2830 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2831 struct pipeline_msg_req *req)
2833 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2834 uint32_t table_id = req->id;
2835 uint32_t meter_profile_id =
2836 req->table_mtr_profile_delete.meter_profile_id;
2837 struct rte_table_action *a = p->table_data[table_id].a;
2839 rsp->status = rte_table_action_meter_profile_delete(a,
2845 static struct pipeline_msg_rsp *
2846 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2847 struct pipeline_msg_req *req)
2849 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2850 uint32_t table_id = req->id;
2851 void *data = req->table_rule_mtr_read.data;
2852 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2853 int clear = req->table_rule_mtr_read.clear;
2854 struct rte_table_action *a = p->table_data[table_id].a;
2856 rsp->status = rte_table_action_meter_read(a,
2859 &rsp->table_rule_mtr_read.stats,
2865 static struct pipeline_msg_rsp *
2866 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2867 struct pipeline_msg_req *req)
2869 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2870 uint32_t table_id = req->id;
2871 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2872 struct rte_table_action_dscp_table *dscp_table =
2873 &req->table_dscp_table_update.dscp_table;
2874 struct rte_table_action *a = p->table_data[table_id].a;
2876 rsp->status = rte_table_action_dscp_table_update(a,
2883 static struct pipeline_msg_rsp *
2884 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2885 struct pipeline_msg_req *req)
2887 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2888 uint32_t table_id = req->id;
2889 void *data = req->table_rule_ttl_read.data;
2890 int clear = req->table_rule_ttl_read.clear;
2891 struct rte_table_action *a = p->table_data[table_id].a;
2893 rsp->status = rte_table_action_ttl_read(a,
2895 &rsp->table_rule_ttl_read.stats,
2902 pipeline_msg_handle(struct pipeline_data *p)
2905 struct pipeline_msg_req *req;
2906 struct pipeline_msg_rsp *rsp;
2908 req = pipeline_msg_recv(p->msgq_req);
2912 switch (req->type) {
2913 case PIPELINE_REQ_PORT_IN_STATS_READ:
2914 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2917 case PIPELINE_REQ_PORT_IN_ENABLE:
2918 rsp = pipeline_msg_handle_port_in_enable(p, req);
2921 case PIPELINE_REQ_PORT_IN_DISABLE:
2922 rsp = pipeline_msg_handle_port_in_disable(p, req);
2925 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2926 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2929 case PIPELINE_REQ_TABLE_STATS_READ:
2930 rsp = pipeline_msg_handle_table_stats_read(p, req);
2933 case PIPELINE_REQ_TABLE_RULE_ADD:
2934 rsp = pipeline_msg_handle_table_rule_add(p, req);
2937 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2938 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2941 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2942 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2945 case PIPELINE_REQ_TABLE_RULE_DELETE:
2946 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2949 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2950 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2953 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2954 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2957 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2958 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
2961 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
2962 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
2965 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
2966 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
2969 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
2970 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
2973 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
2974 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
2978 rsp = (struct pipeline_msg_rsp *)req;
2982 pipeline_msg_send(p->msgq_rsp, rsp);
2987 * Data plane threads: main
2990 rte_pmd_softnic_run_internal(void *arg)
2992 struct rte_eth_dev *dev = arg;
2993 struct pmd_internals *softnic;
2994 struct softnic_thread_data *t;
2995 uint32_t thread_id, j;
2997 softnic = dev->data->dev_private;
2998 thread_id = rte_lcore_id();
2999 t = &softnic->thread_data[thread_id];
3003 for (j = 0; j < t->n_pipelines; j++)
3004 rte_pipeline_run(t->p[j]);
3007 if ((t->iter & 0xFLLU) == 0) {
3008 uint64_t time = rte_get_tsc_cycles();
3009 uint64_t time_next_min = UINT64_MAX;
3011 if (time < t->time_next_min)
3014 /* Pipeline message queues */
3015 for (j = 0; j < t->n_pipelines; j++) {
3016 struct pipeline_data *p =
3017 &t->pipeline_data[j];
3018 uint64_t time_next = p->time_next;
3020 if (time_next <= time) {
3021 pipeline_msg_handle(p);
3022 rte_pipeline_flush(p->p);
3023 time_next = time + p->timer_period;
3024 p->time_next = time_next;
3027 if (time_next < time_next_min)
3028 time_next_min = time_next;
3031 /* Thread message queues */
3033 uint64_t time_next = t->time_next;
3035 if (time_next <= time) {
3036 thread_msg_handle(t);
3037 time_next = time + t->timer_period;
3038 t->time_next = time_next;
3041 if (time_next < time_next_min)
3042 time_next_min = time_next;
3045 t->time_next_min = time_next_min;
3052 rte_pmd_softnic_run(uint16_t port_id)
3054 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3056 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
3057 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
3060 return (int)rte_pmd_softnic_run_internal(dev);