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 if (thread_id == rte_get_master_lcore())
103 return 0; /* FALSE */
105 if (softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_SERVICE))
107 if (!softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_RTE))
110 return 0; /* FALSE */
114 thread_is_running(uint32_t thread_id)
116 enum rte_lcore_state_t thread_state;
118 thread_state = rte_eal_get_lcore_state(thread_id);
119 return (thread_state == RUNNING)? 1 : 0;
123 rte_pmd_softnic_run_internal(void *arg);
126 thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
128 struct rte_service_spec service_params;
129 struct softnic_thread *t = &softnic->thread[thread_id];
130 struct rte_eth_dev *dev;
135 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
139 dev = &rte_eth_devices[port_id];
140 snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
141 softnic->params.name,
143 service_params.callback = rte_pmd_softnic_run_internal;
144 service_params.callback_userdata = dev;
145 service_params.capabilities = 0;
146 service_params.socket_id = (int)softnic->params.cpu_id;
148 /* service register */
149 status = rte_service_component_register(&service_params, &t->service_id);
153 status = rte_service_component_runstate_set(t->service_id, 1);
155 rte_service_component_unregister(t->service_id);
156 t->service_id = UINT32_MAX;
160 status = rte_service_runstate_set(t->service_id, 1);
162 rte_service_component_runstate_set(t->service_id, 0);
163 rte_service_component_unregister(t->service_id);
164 t->service_id = UINT32_MAX;
168 /* service map to thread */
169 status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
171 rte_service_runstate_set(t->service_id, 0);
172 rte_service_component_runstate_set(t->service_id, 0);
173 rte_service_component_unregister(t->service_id);
174 t->service_id = UINT32_MAX;
182 thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
184 struct softnic_thread *t = &softnic->thread[thread_id];
186 /* service unmap from thread */
187 rte_service_map_lcore_set(t->service_id, thread_id, 0);
189 /* service unregister */
190 rte_service_runstate_set(t->service_id, 0);
191 rte_service_component_runstate_set(t->service_id, 0);
192 rte_service_component_unregister(t->service_id);
194 t->service_id = UINT32_MAX;
198 * Pipeline is running when:
199 * (A) Pipeline is mapped to a data plane thread AND
200 * (B) Its data plane thread is in RUNNING state.
203 pipeline_is_running(struct pipeline *p)
208 return thread_is_running(p->thread_id);
212 * Master thread & data plane threads: message passing
214 enum thread_req_type {
215 THREAD_REQ_PIPELINE_ENABLE = 0,
216 THREAD_REQ_PIPELINE_DISABLE,
220 struct thread_msg_req {
221 enum thread_req_type type;
225 struct rte_pipeline *p;
227 struct rte_table_action *a;
228 } table[RTE_PIPELINE_TABLE_MAX];
229 struct rte_ring *msgq_req;
230 struct rte_ring *msgq_rsp;
231 uint32_t timer_period_ms;
236 struct rte_pipeline *p;
241 struct thread_msg_rsp {
248 static struct thread_msg_req *
249 thread_msg_alloc(void)
251 size_t size = RTE_MAX(sizeof(struct thread_msg_req),
252 sizeof(struct thread_msg_rsp));
254 return calloc(1, size);
258 thread_msg_free(struct thread_msg_rsp *rsp)
263 static struct thread_msg_rsp *
264 thread_msg_send_recv(struct pmd_internals *softnic,
266 struct thread_msg_req *req)
268 struct softnic_thread *t = &softnic->thread[thread_id];
269 struct rte_ring *msgq_req = t->msgq_req;
270 struct rte_ring *msgq_rsp = t->msgq_rsp;
271 struct thread_msg_rsp *rsp;
276 status = rte_ring_sp_enqueue(msgq_req, req);
277 } while (status == -ENOBUFS);
281 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
282 } while (status != 0);
288 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
290 const char *pipeline_name)
292 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
293 struct thread_msg_req *req;
294 struct thread_msg_rsp *rsp;
295 uint32_t n_pipelines, i;
298 /* Check input params */
299 if (!thread_is_valid(softnic, thread_id) ||
301 (p->n_ports_in == 0) ||
302 (p->n_ports_out == 0) ||
303 (p->n_tables == 0) ||
307 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
308 if (n_pipelines >= THREAD_PIPELINES_MAX)
311 if (softnic->params.sc && (n_pipelines == 0)) {
312 status = thread_sc_service_up(softnic, thread_id);
317 if (!thread_is_running(thread_id)) {
318 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
319 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
321 /* Data plane thread */
322 td->p[td->n_pipelines] = p->p;
325 for (i = 0; i < p->n_tables; i++)
326 tdp->table_data[i].a =
328 tdp->n_tables = p->n_tables;
330 tdp->msgq_req = p->msgq_req;
331 tdp->msgq_rsp = p->msgq_rsp;
332 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
333 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
338 p->thread_id = thread_id;
344 /* Allocate request */
345 req = thread_msg_alloc();
350 req->type = THREAD_REQ_PIPELINE_ENABLE;
351 req->pipeline_enable.p = p->p;
352 for (i = 0; i < p->n_tables; i++)
353 req->pipeline_enable.table[i].a =
355 req->pipeline_enable.msgq_req = p->msgq_req;
356 req->pipeline_enable.msgq_rsp = p->msgq_rsp;
357 req->pipeline_enable.timer_period_ms = p->timer_period_ms;
358 req->pipeline_enable.n_tables = p->n_tables;
360 /* Send request and wait for response */
361 rsp = thread_msg_send_recv(softnic, thread_id, req);
366 status = rsp->status;
369 thread_msg_free(rsp);
371 /* Request completion */
375 p->thread_id = thread_id;
382 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
384 const char *pipeline_name)
386 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
387 struct thread_msg_req *req;
388 struct thread_msg_rsp *rsp;
389 uint32_t n_pipelines;
392 /* Check input params */
393 if (!thread_is_valid(softnic, thread_id) ||
395 (p->enabled && (p->thread_id != thread_id)))
401 if (!thread_is_running(thread_id)) {
402 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
405 for (i = 0; i < td->n_pipelines; i++) {
406 struct pipeline_data *tdp = &td->pipeline_data[i];
411 /* Data plane thread */
412 if (i < td->n_pipelines - 1) {
413 struct rte_pipeline *pipeline_last =
414 td->p[td->n_pipelines - 1];
415 struct pipeline_data *tdp_last =
416 &td->pipeline_data[td->n_pipelines - 1];
418 td->p[i] = pipeline_last;
419 memcpy(tdp, tdp_last, sizeof(*tdp));
430 if (softnic->params.sc && (td->n_pipelines == 0))
431 thread_sc_service_down(softnic, thread_id);
436 /* Allocate request */
437 req = thread_msg_alloc();
442 req->type = THREAD_REQ_PIPELINE_DISABLE;
443 req->pipeline_disable.p = p->p;
445 /* Send request and wait for response */
446 rsp = thread_msg_send_recv(softnic, thread_id, req);
451 status = rsp->status;
454 thread_msg_free(rsp);
456 /* Request completion */
462 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
463 if (softnic->params.sc && (n_pipelines == 0))
464 thread_sc_service_down(softnic, thread_id);
470 * Data plane threads: message handling
472 static inline struct thread_msg_req *
473 thread_msg_recv(struct rte_ring *msgq_req)
475 struct thread_msg_req *req;
477 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
486 thread_msg_send(struct rte_ring *msgq_rsp,
487 struct thread_msg_rsp *rsp)
492 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
493 } while (status == -ENOBUFS);
496 static struct thread_msg_rsp *
497 thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
498 struct thread_msg_req *req)
500 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
501 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
505 t->p[t->n_pipelines] = req->pipeline_enable.p;
507 p->p = req->pipeline_enable.p;
508 for (i = 0; i < req->pipeline_enable.n_tables; i++)
510 req->pipeline_enable.table[i].a;
512 p->n_tables = req->pipeline_enable.n_tables;
514 p->msgq_req = req->pipeline_enable.msgq_req;
515 p->msgq_rsp = req->pipeline_enable.msgq_rsp;
517 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
518 p->time_next = rte_get_tsc_cycles() + p->timer_period;
527 static struct thread_msg_rsp *
528 thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
529 struct thread_msg_req *req)
531 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
532 uint32_t n_pipelines = t->n_pipelines;
533 struct rte_pipeline *pipeline = req->pipeline_disable.p;
537 for (i = 0; i < n_pipelines; i++) {
538 struct pipeline_data *p = &t->pipeline_data[i];
540 if (p->p != pipeline)
543 if (i < n_pipelines - 1) {
544 struct rte_pipeline *pipeline_last =
545 t->p[n_pipelines - 1];
546 struct pipeline_data *p_last =
547 &t->pipeline_data[n_pipelines - 1];
549 t->p[i] = pipeline_last;
550 memcpy(p, p_last, sizeof(*p));
559 /* should not get here */
565 thread_msg_handle(struct softnic_thread_data *t)
568 struct thread_msg_req *req;
569 struct thread_msg_rsp *rsp;
571 req = thread_msg_recv(t->msgq_req);
576 case THREAD_REQ_PIPELINE_ENABLE:
577 rsp = thread_msg_handle_pipeline_enable(t, req);
580 case THREAD_REQ_PIPELINE_DISABLE:
581 rsp = thread_msg_handle_pipeline_disable(t, req);
585 rsp = (struct thread_msg_rsp *)req;
589 thread_msg_send(t->msgq_rsp, rsp);
594 * Master thread & data plane threads: message passing
596 enum pipeline_req_type {
598 PIPELINE_REQ_PORT_IN_STATS_READ,
599 PIPELINE_REQ_PORT_IN_ENABLE,
600 PIPELINE_REQ_PORT_IN_DISABLE,
603 PIPELINE_REQ_PORT_OUT_STATS_READ,
606 PIPELINE_REQ_TABLE_STATS_READ,
607 PIPELINE_REQ_TABLE_RULE_ADD,
608 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
609 PIPELINE_REQ_TABLE_RULE_ADD_BULK,
610 PIPELINE_REQ_TABLE_RULE_DELETE,
611 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
612 PIPELINE_REQ_TABLE_RULE_STATS_READ,
613 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
614 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
615 PIPELINE_REQ_TABLE_RULE_MTR_READ,
616 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
617 PIPELINE_REQ_TABLE_RULE_TTL_READ,
621 struct pipeline_msg_req_port_in_stats_read {
625 struct pipeline_msg_req_port_out_stats_read {
629 struct pipeline_msg_req_table_stats_read {
633 struct pipeline_msg_req_table_rule_add {
634 struct softnic_table_rule_match match;
635 struct softnic_table_rule_action action;
638 struct pipeline_msg_req_table_rule_add_default {
639 struct softnic_table_rule_action action;
642 struct pipeline_msg_req_table_rule_add_bulk {
643 struct softnic_table_rule_match *match;
644 struct softnic_table_rule_action *action;
650 struct pipeline_msg_req_table_rule_delete {
651 struct softnic_table_rule_match match;
654 struct pipeline_msg_req_table_rule_stats_read {
659 struct pipeline_msg_req_table_mtr_profile_add {
660 uint32_t meter_profile_id;
661 struct rte_table_action_meter_profile profile;
664 struct pipeline_msg_req_table_mtr_profile_delete {
665 uint32_t meter_profile_id;
668 struct pipeline_msg_req_table_rule_mtr_read {
674 struct pipeline_msg_req_table_dscp_table_update {
676 struct rte_table_action_dscp_table dscp_table;
679 struct pipeline_msg_req_table_rule_ttl_read {
684 struct pipeline_msg_req {
685 enum pipeline_req_type type;
686 uint32_t id; /* Port IN, port OUT or table ID */
690 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
691 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
692 struct pipeline_msg_req_table_stats_read table_stats_read;
693 struct pipeline_msg_req_table_rule_add table_rule_add;
694 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
695 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
696 struct pipeline_msg_req_table_rule_delete table_rule_delete;
697 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
698 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
699 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
700 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
701 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
702 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
706 struct pipeline_msg_rsp_port_in_stats_read {
707 struct rte_pipeline_port_in_stats stats;
710 struct pipeline_msg_rsp_port_out_stats_read {
711 struct rte_pipeline_port_out_stats stats;
714 struct pipeline_msg_rsp_table_stats_read {
715 struct rte_pipeline_table_stats stats;
718 struct pipeline_msg_rsp_table_rule_add {
722 struct pipeline_msg_rsp_table_rule_add_default {
726 struct pipeline_msg_rsp_table_rule_add_bulk {
730 struct pipeline_msg_rsp_table_rule_stats_read {
731 struct rte_table_action_stats_counters stats;
734 struct pipeline_msg_rsp_table_rule_mtr_read {
735 struct rte_table_action_mtr_counters stats;
738 struct pipeline_msg_rsp_table_rule_ttl_read {
739 struct rte_table_action_ttl_counters stats;
742 struct pipeline_msg_rsp {
747 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
748 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
749 struct pipeline_msg_rsp_table_stats_read table_stats_read;
750 struct pipeline_msg_rsp_table_rule_add table_rule_add;
751 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
752 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
753 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
754 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
755 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
762 static struct pipeline_msg_req *
763 pipeline_msg_alloc(void)
765 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
766 sizeof(struct pipeline_msg_rsp));
768 return calloc(1, size);
772 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
777 static struct pipeline_msg_rsp *
778 pipeline_msg_send_recv(struct pipeline *p,
779 struct pipeline_msg_req *req)
781 struct rte_ring *msgq_req = p->msgq_req;
782 struct rte_ring *msgq_rsp = p->msgq_rsp;
783 struct pipeline_msg_rsp *rsp;
788 status = rte_ring_sp_enqueue(msgq_req, req);
789 } while (status == -ENOBUFS);
793 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
794 } while (status != 0);
800 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
801 const char *pipeline_name,
803 struct rte_pipeline_port_in_stats *stats,
807 struct pipeline_msg_req *req;
808 struct pipeline_msg_rsp *rsp;
811 /* Check input params */
812 if (pipeline_name == NULL ||
816 p = softnic_pipeline_find(softnic, pipeline_name);
818 port_id >= p->n_ports_in)
821 if (!pipeline_is_running(p)) {
822 status = rte_pipeline_port_in_stats_read(p->p,
830 /* Allocate request */
831 req = pipeline_msg_alloc();
836 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
838 req->port_in_stats_read.clear = clear;
840 /* Send request and wait for response */
841 rsp = pipeline_msg_send_recv(p, req);
846 status = rsp->status;
848 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
851 pipeline_msg_free(rsp);
857 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
858 const char *pipeline_name,
862 struct pipeline_msg_req *req;
863 struct pipeline_msg_rsp *rsp;
866 /* Check input params */
867 if (pipeline_name == NULL)
870 p = softnic_pipeline_find(softnic, pipeline_name);
872 port_id >= p->n_ports_in)
875 if (!pipeline_is_running(p)) {
876 status = rte_pipeline_port_in_enable(p->p, port_id);
880 /* Allocate request */
881 req = pipeline_msg_alloc();
886 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
889 /* Send request and wait for response */
890 rsp = pipeline_msg_send_recv(p, req);
895 status = rsp->status;
898 pipeline_msg_free(rsp);
904 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
905 const char *pipeline_name,
909 struct pipeline_msg_req *req;
910 struct pipeline_msg_rsp *rsp;
913 /* Check input params */
914 if (pipeline_name == NULL)
917 p = softnic_pipeline_find(softnic, pipeline_name);
919 port_id >= p->n_ports_in)
922 if (!pipeline_is_running(p)) {
923 status = rte_pipeline_port_in_disable(p->p, port_id);
927 /* Allocate request */
928 req = pipeline_msg_alloc();
933 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
936 /* Send request and wait for response */
937 rsp = pipeline_msg_send_recv(p, req);
942 status = rsp->status;
945 pipeline_msg_free(rsp);
951 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
952 const char *pipeline_name,
954 struct rte_pipeline_port_out_stats *stats,
958 struct pipeline_msg_req *req;
959 struct pipeline_msg_rsp *rsp;
962 /* Check input params */
963 if (pipeline_name == NULL ||
967 p = softnic_pipeline_find(softnic, pipeline_name);
969 port_id >= p->n_ports_out)
972 if (!pipeline_is_running(p)) {
973 status = rte_pipeline_port_out_stats_read(p->p,
981 /* Allocate request */
982 req = pipeline_msg_alloc();
987 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
989 req->port_out_stats_read.clear = clear;
991 /* Send request and wait for response */
992 rsp = pipeline_msg_send_recv(p, req);
997 status = rsp->status;
999 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
1002 pipeline_msg_free(rsp);
1008 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
1009 const char *pipeline_name,
1011 struct rte_pipeline_table_stats *stats,
1015 struct pipeline_msg_req *req;
1016 struct pipeline_msg_rsp *rsp;
1019 /* Check input params */
1020 if (pipeline_name == NULL ||
1024 p = softnic_pipeline_find(softnic, pipeline_name);
1026 table_id >= p->n_tables)
1029 if (!pipeline_is_running(p)) {
1030 status = rte_pipeline_table_stats_read(p->p,
1038 /* Allocate request */
1039 req = pipeline_msg_alloc();
1044 req->type = PIPELINE_REQ_TABLE_STATS_READ;
1046 req->table_stats_read.clear = clear;
1048 /* Send request and wait for response */
1049 rsp = pipeline_msg_send_recv(p, req);
1054 status = rsp->status;
1056 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
1059 pipeline_msg_free(rsp);
1065 match_check(struct softnic_table_rule_match *match,
1069 struct softnic_table *table;
1071 if (match == NULL ||
1073 table_id >= p->n_tables)
1076 table = &p->table[table_id];
1077 if (match->match_type != table->params.match_type)
1080 switch (match->match_type) {
1083 struct softnic_table_acl_params *t = &table->params.match.acl;
1084 struct softnic_table_rule_match_acl *r = &match->match.acl;
1086 if ((r->ip_version && (t->ip_version == 0)) ||
1087 ((r->ip_version == 0) && t->ip_version))
1090 if (r->ip_version) {
1091 if (r->sa_depth > 32 ||
1095 if (r->sa_depth > 128 ||
1110 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1111 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1113 if ((r->ip_version && (t->key_size != 4)) ||
1114 ((r->ip_version == 0) && (t->key_size != 16)))
1117 if (r->ip_version) {
1136 action_check(struct softnic_table_rule_action *action,
1140 struct softnic_table_action_profile *ap;
1142 if (action == NULL ||
1144 table_id >= p->n_tables)
1147 ap = p->table[table_id].ap;
1148 if (action->action_mask != ap->params.action_mask)
1151 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1152 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1153 action->fwd.id >= p->n_ports_out)
1156 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1157 action->fwd.id >= p->n_tables)
1161 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1162 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1163 uint32_t tc_mask1 = action->mtr.tc_mask;
1165 if (tc_mask1 != tc_mask0)
1169 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1170 uint32_t n_subports_per_port =
1171 ap->params.tm.n_subports_per_port;
1172 uint32_t n_pipes_per_subport =
1173 ap->params.tm.n_pipes_per_subport;
1174 uint32_t subport_id = action->tm.subport_id;
1175 uint32_t pipe_id = action->tm.pipe_id;
1177 if (subport_id >= n_subports_per_port ||
1178 pipe_id >= n_pipes_per_subport)
1182 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1183 uint64_t encap_mask = ap->params.encap.encap_mask;
1184 enum rte_table_action_encap_type type = action->encap.type;
1186 if ((encap_mask & (1LLU << type)) == 0)
1190 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1191 int ip_version0 = ap->params.common.ip_version;
1192 int ip_version1 = action->nat.ip_version;
1194 if ((ip_version1 && (ip_version0 == 0)) ||
1195 ((ip_version1 == 0) && ip_version0))
1203 action_default_check(struct softnic_table_rule_action *action,
1207 if (action == NULL ||
1208 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1210 table_id >= p->n_tables)
1213 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1214 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1215 action->fwd.id >= p->n_ports_out)
1218 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1219 action->fwd.id >= p->n_tables)
1226 union table_rule_match_low_level {
1227 struct rte_table_acl_rule_add_params acl_add;
1228 struct rte_table_acl_rule_delete_params acl_delete;
1229 struct rte_table_array_key array;
1230 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1231 struct rte_table_lpm_key lpm_ipv4;
1232 struct rte_table_lpm_ipv6_key lpm_ipv6;
1236 match_convert(struct softnic_table_rule_match *mh,
1237 union table_rule_match_low_level *ml,
1241 action_convert(struct rte_table_action *a,
1242 struct softnic_table_rule_action *action,
1243 struct rte_pipeline_table_entry *data);
1246 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1247 const char *pipeline_name,
1249 struct softnic_table_rule_match *match,
1250 struct softnic_table_rule_action *action,
1254 struct pipeline_msg_req *req;
1255 struct pipeline_msg_rsp *rsp;
1258 /* Check input params */
1259 if (pipeline_name == NULL ||
1265 p = softnic_pipeline_find(softnic, pipeline_name);
1267 table_id >= p->n_tables ||
1268 match_check(match, p, table_id) ||
1269 action_check(action, p, table_id))
1272 if (!pipeline_is_running(p)) {
1273 struct rte_table_action *a = p->table[table_id].a;
1274 union table_rule_match_low_level match_ll;
1275 struct rte_pipeline_table_entry *data_in, *data_out;
1279 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1283 /* Table match-action rule conversion */
1284 data_in = (struct rte_pipeline_table_entry *)buffer;
1286 status = match_convert(match, &match_ll, 1);
1292 status = action_convert(a, action, data_in);
1298 /* Add rule (match, action) to table */
1299 status = rte_pipeline_table_entry_add(p->p,
1310 /* Write Response */
1317 /* Allocate request */
1318 req = pipeline_msg_alloc();
1323 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1325 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1326 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1328 /* Send request and wait for response */
1329 rsp = pipeline_msg_send_recv(p, req);
1334 status = rsp->status;
1336 *data = rsp->table_rule_add.data;
1339 pipeline_msg_free(rsp);
1345 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1346 const char *pipeline_name,
1348 struct softnic_table_rule_action *action,
1352 struct pipeline_msg_req *req;
1353 struct pipeline_msg_rsp *rsp;
1356 /* Check input params */
1357 if (pipeline_name == NULL ||
1362 p = softnic_pipeline_find(softnic, pipeline_name);
1364 table_id >= p->n_tables ||
1365 action_default_check(action, p, table_id))
1368 if (!pipeline_is_running(p)) {
1369 struct rte_pipeline_table_entry *data_in, *data_out;
1372 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1377 data_in = (struct rte_pipeline_table_entry *)buffer;
1379 data_in->action = action->fwd.action;
1380 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1381 data_in->port_id = action->fwd.id;
1382 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1383 data_in->table_id = action->fwd.id;
1385 /* Add default rule to table */
1386 status = rte_pipeline_table_default_entry_add(p->p,
1395 /* Write Response */
1402 /* Allocate request */
1403 req = pipeline_msg_alloc();
1408 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1410 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1412 /* Send request and wait for response */
1413 rsp = pipeline_msg_send_recv(p, req);
1418 status = rsp->status;
1420 *data = rsp->table_rule_add_default.data;
1423 pipeline_msg_free(rsp);
1429 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1430 const char *pipeline_name,
1432 struct softnic_table_rule_match *match,
1433 struct softnic_table_rule_action *action,
1438 struct pipeline_msg_req *req;
1439 struct pipeline_msg_rsp *rsp;
1443 /* Check input params */
1444 if (pipeline_name == NULL ||
1452 p = softnic_pipeline_find(softnic, pipeline_name);
1454 table_id >= p->n_tables)
1457 for (i = 0; i < *n_rules; i++)
1458 if (match_check(match, p, table_id) ||
1459 action_check(action, p, table_id))
1462 if (!pipeline_is_running(p)) {
1463 struct rte_table_action *a = p->table[table_id].a;
1464 union table_rule_match_low_level *match_ll;
1466 void **match_ll_ptr;
1467 struct rte_pipeline_table_entry **action_ll_ptr;
1468 struct rte_pipeline_table_entry **entries_ptr =
1469 (struct rte_pipeline_table_entry **)data;
1471 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1474 /* Memory allocation */
1475 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1476 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1477 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1479 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1480 found = calloc(*n_rules, sizeof(int));
1482 if (match_ll == NULL ||
1483 action_ll == NULL ||
1484 match_ll_ptr == NULL ||
1485 action_ll_ptr == NULL ||
1489 for (i = 0; i < *n_rules; i++) {
1490 match_ll_ptr[i] = (void *)&match_ll[i];
1492 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1495 /* Rule match conversion */
1496 for (i = 0; i < *n_rules; i++) {
1497 status = match_convert(&match[i], match_ll_ptr[i], 1);
1502 /* Rule action conversion */
1503 for (i = 0; i < *n_rules; i++) {
1504 status = action_convert(a, &action[i], action_ll_ptr[i]);
1509 /* Add rule (match, action) to table */
1511 status = rte_pipeline_table_entry_add_bulk(p->p,
1521 for (i = 0; i < *n_rules; i++) {
1522 status = rte_pipeline_table_entry_add(p->p,
1537 free(action_ll_ptr);
1546 free(action_ll_ptr);
1555 /* Allocate request */
1556 req = pipeline_msg_alloc();
1561 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1563 req->table_rule_add_bulk.match = match;
1564 req->table_rule_add_bulk.action = action;
1565 req->table_rule_add_bulk.data = data;
1566 req->table_rule_add_bulk.n_rules = *n_rules;
1567 req->table_rule_add_bulk.bulk =
1568 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1570 /* Send request and wait for response */
1571 rsp = pipeline_msg_send_recv(p, req);
1576 status = rsp->status;
1578 *n_rules = rsp->table_rule_add_bulk.n_rules;
1581 pipeline_msg_free(rsp);
1587 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1588 const char *pipeline_name,
1590 struct softnic_table_rule_match *match)
1593 struct pipeline_msg_req *req;
1594 struct pipeline_msg_rsp *rsp;
1597 /* Check input params */
1598 if (pipeline_name == NULL ||
1602 p = softnic_pipeline_find(softnic, pipeline_name);
1604 table_id >= p->n_tables ||
1605 match_check(match, p, table_id))
1608 if (!pipeline_is_running(p)) {
1609 union table_rule_match_low_level match_ll;
1612 status = match_convert(match, &match_ll, 0);
1616 status = rte_pipeline_table_entry_delete(p->p,
1625 /* Allocate request */
1626 req = pipeline_msg_alloc();
1631 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1633 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1635 /* Send request and wait for response */
1636 rsp = pipeline_msg_send_recv(p, req);
1641 status = rsp->status;
1644 pipeline_msg_free(rsp);
1650 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1651 const char *pipeline_name,
1655 struct pipeline_msg_req *req;
1656 struct pipeline_msg_rsp *rsp;
1659 /* Check input params */
1660 if (pipeline_name == NULL)
1663 p = softnic_pipeline_find(softnic, pipeline_name);
1665 table_id >= p->n_tables)
1668 if (!pipeline_is_running(p)) {
1669 status = rte_pipeline_table_default_entry_delete(p->p,
1676 /* Allocate request */
1677 req = pipeline_msg_alloc();
1682 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1685 /* Send request and wait for response */
1686 rsp = pipeline_msg_send_recv(p, req);
1691 status = rsp->status;
1694 pipeline_msg_free(rsp);
1700 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1701 const char *pipeline_name,
1704 struct rte_table_action_stats_counters *stats,
1708 struct pipeline_msg_req *req;
1709 struct pipeline_msg_rsp *rsp;
1712 /* Check input params */
1713 if (pipeline_name == NULL ||
1718 p = softnic_pipeline_find(softnic, pipeline_name);
1720 table_id >= p->n_tables)
1723 if (!pipeline_is_running(p)) {
1724 struct rte_table_action *a = p->table[table_id].a;
1726 status = rte_table_action_stats_read(a,
1734 /* Allocate request */
1735 req = pipeline_msg_alloc();
1740 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1742 req->table_rule_stats_read.data = data;
1743 req->table_rule_stats_read.clear = clear;
1745 /* Send request and wait for response */
1746 rsp = pipeline_msg_send_recv(p, req);
1751 status = rsp->status;
1753 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1756 pipeline_msg_free(rsp);
1762 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1763 const char *pipeline_name,
1765 uint32_t meter_profile_id,
1766 struct rte_table_action_meter_profile *profile)
1769 struct pipeline_msg_req *req;
1770 struct pipeline_msg_rsp *rsp;
1771 struct softnic_table *table;
1772 struct softnic_table_meter_profile *mp;
1775 /* Check input params */
1776 if (pipeline_name == NULL ||
1780 p = softnic_pipeline_find(softnic, pipeline_name);
1782 table_id >= p->n_tables)
1785 table = &p->table[table_id];
1786 mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
1790 /* Resource Allocation */
1791 mp = calloc(1, sizeof(struct softnic_table_meter_profile));
1795 mp->meter_profile_id = meter_profile_id;
1796 memcpy(&mp->profile, profile, sizeof(mp->profile));
1798 if (!pipeline_is_running(p)) {
1799 status = rte_table_action_meter_profile_add(table->a,
1807 /* Add profile to the table. */
1808 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1813 /* Allocate request */
1814 req = pipeline_msg_alloc();
1821 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1823 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1824 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1826 /* Send request and wait for response */
1827 rsp = pipeline_msg_send_recv(p, req);
1834 status = rsp->status;
1836 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1841 pipeline_msg_free(rsp);
1847 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1848 const char *pipeline_name,
1850 uint32_t meter_profile_id)
1853 struct pipeline_msg_req *req;
1854 struct pipeline_msg_rsp *rsp;
1857 /* Check input params */
1858 if (pipeline_name == NULL)
1861 p = softnic_pipeline_find(softnic, pipeline_name);
1863 table_id >= p->n_tables)
1866 if (!pipeline_is_running(p)) {
1867 struct rte_table_action *a = p->table[table_id].a;
1869 status = rte_table_action_meter_profile_delete(a,
1875 /* Allocate request */
1876 req = pipeline_msg_alloc();
1881 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1883 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1885 /* Send request and wait for response */
1886 rsp = pipeline_msg_send_recv(p, req);
1891 status = rsp->status;
1894 pipeline_msg_free(rsp);
1900 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1901 const char *pipeline_name,
1905 struct rte_table_action_mtr_counters *stats,
1909 struct pipeline_msg_req *req;
1910 struct pipeline_msg_rsp *rsp;
1913 /* Check input params */
1914 if (pipeline_name == NULL ||
1919 p = softnic_pipeline_find(softnic, pipeline_name);
1921 table_id >= p->n_tables)
1924 if (!pipeline_is_running(p)) {
1925 struct rte_table_action *a = p->table[table_id].a;
1927 status = rte_table_action_meter_read(a,
1936 /* Allocate request */
1937 req = pipeline_msg_alloc();
1942 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1944 req->table_rule_mtr_read.data = data;
1945 req->table_rule_mtr_read.tc_mask = tc_mask;
1946 req->table_rule_mtr_read.clear = clear;
1948 /* Send request and wait for response */
1949 rsp = pipeline_msg_send_recv(p, req);
1954 status = rsp->status;
1956 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1959 pipeline_msg_free(rsp);
1965 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1966 const char *pipeline_name,
1969 struct rte_table_action_dscp_table *dscp_table)
1972 struct pipeline_msg_req *req;
1973 struct pipeline_msg_rsp *rsp;
1976 /* Check input params */
1977 if (pipeline_name == NULL ||
1981 p = softnic_pipeline_find(softnic, pipeline_name);
1983 table_id >= p->n_tables)
1986 if (!pipeline_is_running(p)) {
1987 struct rte_table_action *a = p->table[table_id].a;
1989 status = rte_table_action_dscp_table_update(a,
1993 /* Update table dscp table */
1995 memcpy(&p->table[table_id].dscp_table, dscp_table,
1996 sizeof(p->table[table_id].dscp_table));
2001 /* Allocate request */
2002 req = pipeline_msg_alloc();
2007 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
2009 req->table_dscp_table_update.dscp_mask = dscp_mask;
2010 memcpy(&req->table_dscp_table_update.dscp_table,
2011 dscp_table, sizeof(*dscp_table));
2013 /* Send request and wait for response */
2014 rsp = pipeline_msg_send_recv(p, req);
2019 status = rsp->status;
2021 /* Update table dscp table */
2023 memcpy(&p->table[table_id].dscp_table, dscp_table,
2024 sizeof(p->table[table_id].dscp_table));
2027 pipeline_msg_free(rsp);
2033 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
2034 const char *pipeline_name,
2037 struct rte_table_action_ttl_counters *stats,
2041 struct pipeline_msg_req *req;
2042 struct pipeline_msg_rsp *rsp;
2045 /* Check input params */
2046 if (pipeline_name == NULL ||
2051 p = softnic_pipeline_find(softnic, pipeline_name);
2053 table_id >= p->n_tables)
2056 if (!pipeline_is_running(p)) {
2057 struct rte_table_action *a = p->table[table_id].a;
2059 status = rte_table_action_ttl_read(a,
2067 /* Allocate request */
2068 req = pipeline_msg_alloc();
2073 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
2075 req->table_rule_ttl_read.data = data;
2076 req->table_rule_ttl_read.clear = clear;
2078 /* Send request and wait for response */
2079 rsp = pipeline_msg_send_recv(p, req);
2084 status = rsp->status;
2086 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2089 pipeline_msg_free(rsp);
2095 * Data plane threads: message handling
2097 static inline struct pipeline_msg_req *
2098 pipeline_msg_recv(struct rte_ring *msgq_req)
2100 struct pipeline_msg_req *req;
2102 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2111 pipeline_msg_send(struct rte_ring *msgq_rsp,
2112 struct pipeline_msg_rsp *rsp)
2117 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2118 } while (status == -ENOBUFS);
2121 static struct pipeline_msg_rsp *
2122 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2123 struct pipeline_msg_req *req)
2125 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2126 uint32_t port_id = req->id;
2127 int clear = req->port_in_stats_read.clear;
2129 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2131 &rsp->port_in_stats_read.stats,
2137 static struct pipeline_msg_rsp *
2138 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2139 struct pipeline_msg_req *req)
2141 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2142 uint32_t port_id = req->id;
2144 rsp->status = rte_pipeline_port_in_enable(p->p,
2150 static struct pipeline_msg_rsp *
2151 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2152 struct pipeline_msg_req *req)
2154 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2155 uint32_t port_id = req->id;
2157 rsp->status = rte_pipeline_port_in_disable(p->p,
2163 static struct pipeline_msg_rsp *
2164 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2165 struct pipeline_msg_req *req)
2167 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2168 uint32_t port_id = req->id;
2169 int clear = req->port_out_stats_read.clear;
2171 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2173 &rsp->port_out_stats_read.stats,
2179 static struct pipeline_msg_rsp *
2180 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2181 struct pipeline_msg_req *req)
2183 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2184 uint32_t port_id = req->id;
2185 int clear = req->table_stats_read.clear;
2187 rsp->status = rte_pipeline_table_stats_read(p->p,
2189 &rsp->table_stats_read.stats,
2196 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2201 switch (depth / 32) {
2211 depth32[1] = depth - 32;
2219 depth32[2] = depth - 64;
2227 depth32[3] = depth - 96;
2243 match_convert(struct softnic_table_rule_match *mh,
2244 union table_rule_match_low_level *ml,
2247 memset(ml, 0, sizeof(*ml));
2249 switch (mh->match_type) {
2251 if (mh->match.acl.ip_version)
2253 ml->acl_add.field_value[0].value.u8 =
2254 mh->match.acl.proto;
2255 ml->acl_add.field_value[0].mask_range.u8 =
2256 mh->match.acl.proto_mask;
2258 ml->acl_add.field_value[1].value.u32 =
2259 mh->match.acl.ipv4.sa;
2260 ml->acl_add.field_value[1].mask_range.u32 =
2261 mh->match.acl.sa_depth;
2263 ml->acl_add.field_value[2].value.u32 =
2264 mh->match.acl.ipv4.da;
2265 ml->acl_add.field_value[2].mask_range.u32 =
2266 mh->match.acl.da_depth;
2268 ml->acl_add.field_value[3].value.u16 =
2270 ml->acl_add.field_value[3].mask_range.u16 =
2273 ml->acl_add.field_value[4].value.u16 =
2275 ml->acl_add.field_value[4].mask_range.u16 =
2278 ml->acl_add.priority =
2279 (int32_t)mh->match.acl.priority;
2281 ml->acl_delete.field_value[0].value.u8 =
2282 mh->match.acl.proto;
2283 ml->acl_delete.field_value[0].mask_range.u8 =
2284 mh->match.acl.proto_mask;
2286 ml->acl_delete.field_value[1].value.u32 =
2287 mh->match.acl.ipv4.sa;
2288 ml->acl_delete.field_value[1].mask_range.u32 =
2289 mh->match.acl.sa_depth;
2291 ml->acl_delete.field_value[2].value.u32 =
2292 mh->match.acl.ipv4.da;
2293 ml->acl_delete.field_value[2].mask_range.u32 =
2294 mh->match.acl.da_depth;
2296 ml->acl_delete.field_value[3].value.u16 =
2298 ml->acl_delete.field_value[3].mask_range.u16 =
2301 ml->acl_delete.field_value[4].value.u16 =
2303 ml->acl_delete.field_value[4].mask_range.u16 =
2309 (uint32_t *)mh->match.acl.ipv6.sa;
2311 (uint32_t *)mh->match.acl.ipv6.da;
2312 uint32_t sa32_depth[4], da32_depth[4];
2315 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2320 status = match_convert_ipv6_depth(
2321 mh->match.acl.da_depth,
2326 ml->acl_add.field_value[0].value.u8 =
2327 mh->match.acl.proto;
2328 ml->acl_add.field_value[0].mask_range.u8 =
2329 mh->match.acl.proto_mask;
2331 ml->acl_add.field_value[1].value.u32 =
2332 rte_be_to_cpu_32(sa32[0]);
2333 ml->acl_add.field_value[1].mask_range.u32 =
2335 ml->acl_add.field_value[2].value.u32 =
2336 rte_be_to_cpu_32(sa32[1]);
2337 ml->acl_add.field_value[2].mask_range.u32 =
2339 ml->acl_add.field_value[3].value.u32 =
2340 rte_be_to_cpu_32(sa32[2]);
2341 ml->acl_add.field_value[3].mask_range.u32 =
2343 ml->acl_add.field_value[4].value.u32 =
2344 rte_be_to_cpu_32(sa32[3]);
2345 ml->acl_add.field_value[4].mask_range.u32 =
2348 ml->acl_add.field_value[5].value.u32 =
2349 rte_be_to_cpu_32(da32[0]);
2350 ml->acl_add.field_value[5].mask_range.u32 =
2352 ml->acl_add.field_value[6].value.u32 =
2353 rte_be_to_cpu_32(da32[1]);
2354 ml->acl_add.field_value[6].mask_range.u32 =
2356 ml->acl_add.field_value[7].value.u32 =
2357 rte_be_to_cpu_32(da32[2]);
2358 ml->acl_add.field_value[7].mask_range.u32 =
2360 ml->acl_add.field_value[8].value.u32 =
2361 rte_be_to_cpu_32(da32[3]);
2362 ml->acl_add.field_value[8].mask_range.u32 =
2365 ml->acl_add.field_value[9].value.u16 =
2367 ml->acl_add.field_value[9].mask_range.u16 =
2370 ml->acl_add.field_value[10].value.u16 =
2372 ml->acl_add.field_value[10].mask_range.u16 =
2375 ml->acl_add.priority =
2376 (int32_t)mh->match.acl.priority;
2379 (uint32_t *)mh->match.acl.ipv6.sa;
2381 (uint32_t *)mh->match.acl.ipv6.da;
2382 uint32_t sa32_depth[4], da32_depth[4];
2385 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2390 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2395 ml->acl_delete.field_value[0].value.u8 =
2396 mh->match.acl.proto;
2397 ml->acl_delete.field_value[0].mask_range.u8 =
2398 mh->match.acl.proto_mask;
2400 ml->acl_delete.field_value[1].value.u32 =
2401 rte_be_to_cpu_32(sa32[0]);
2402 ml->acl_delete.field_value[1].mask_range.u32 =
2404 ml->acl_delete.field_value[2].value.u32 =
2405 rte_be_to_cpu_32(sa32[1]);
2406 ml->acl_delete.field_value[2].mask_range.u32 =
2408 ml->acl_delete.field_value[3].value.u32 =
2409 rte_be_to_cpu_32(sa32[2]);
2410 ml->acl_delete.field_value[3].mask_range.u32 =
2412 ml->acl_delete.field_value[4].value.u32 =
2413 rte_be_to_cpu_32(sa32[3]);
2414 ml->acl_delete.field_value[4].mask_range.u32 =
2417 ml->acl_delete.field_value[5].value.u32 =
2418 rte_be_to_cpu_32(da32[0]);
2419 ml->acl_delete.field_value[5].mask_range.u32 =
2421 ml->acl_delete.field_value[6].value.u32 =
2422 rte_be_to_cpu_32(da32[1]);
2423 ml->acl_delete.field_value[6].mask_range.u32 =
2425 ml->acl_delete.field_value[7].value.u32 =
2426 rte_be_to_cpu_32(da32[2]);
2427 ml->acl_delete.field_value[7].mask_range.u32 =
2429 ml->acl_delete.field_value[8].value.u32 =
2430 rte_be_to_cpu_32(da32[3]);
2431 ml->acl_delete.field_value[8].mask_range.u32 =
2434 ml->acl_delete.field_value[9].value.u16 =
2436 ml->acl_delete.field_value[9].mask_range.u16 =
2439 ml->acl_delete.field_value[10].value.u16 =
2441 ml->acl_delete.field_value[10].mask_range.u16 =
2447 ml->array.pos = mh->match.array.pos;
2451 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2455 if (mh->match.lpm.ip_version) {
2456 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2457 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2459 memcpy(ml->lpm_ipv6.ip,
2460 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2461 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2472 action_convert(struct rte_table_action *a,
2473 struct softnic_table_rule_action *action,
2474 struct rte_pipeline_table_entry *data)
2479 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2480 status = rte_table_action_apply(a,
2482 RTE_TABLE_ACTION_FWD,
2489 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2490 status = rte_table_action_apply(a,
2492 RTE_TABLE_ACTION_LB,
2499 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2500 status = rte_table_action_apply(a,
2502 RTE_TABLE_ACTION_MTR,
2509 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2510 status = rte_table_action_apply(a,
2512 RTE_TABLE_ACTION_TM,
2519 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2520 status = rte_table_action_apply(a,
2522 RTE_TABLE_ACTION_ENCAP,
2529 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2530 status = rte_table_action_apply(a,
2532 RTE_TABLE_ACTION_NAT,
2539 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2540 status = rte_table_action_apply(a,
2542 RTE_TABLE_ACTION_TTL,
2549 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2550 status = rte_table_action_apply(a,
2552 RTE_TABLE_ACTION_STATS,
2559 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2560 status = rte_table_action_apply(a,
2562 RTE_TABLE_ACTION_TIME,
2569 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2570 status = rte_table_action_apply(a,
2572 RTE_TABLE_ACTION_TAG,
2579 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2580 status = rte_table_action_apply(a,
2582 RTE_TABLE_ACTION_DECAP,
2589 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2590 status = rte_table_action_apply(a,
2592 RTE_TABLE_ACTION_SYM_CRYPTO,
2593 &action->sym_crypto);
2602 static struct pipeline_msg_rsp *
2603 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2604 struct pipeline_msg_req *req)
2606 union table_rule_match_low_level match_ll;
2607 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2608 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2609 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2610 struct rte_pipeline_table_entry *data_in, *data_out;
2611 uint32_t table_id = req->id;
2612 int key_found, status;
2613 struct rte_table_action *a = p->table_data[table_id].a;
2616 memset(p->buffer, 0, sizeof(p->buffer));
2617 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2619 status = match_convert(match, &match_ll, 1);
2625 status = action_convert(a, action, data_in);
2631 status = rte_pipeline_table_entry_add(p->p,
2642 /* Write response */
2644 rsp->table_rule_add.data = data_out;
2649 static struct pipeline_msg_rsp *
2650 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2651 struct pipeline_msg_req *req)
2653 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2654 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2655 struct rte_pipeline_table_entry *data_in, *data_out;
2656 uint32_t table_id = req->id;
2660 memset(p->buffer, 0, sizeof(p->buffer));
2661 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2663 data_in->action = action->fwd.action;
2664 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2665 data_in->port_id = action->fwd.id;
2666 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2667 data_in->table_id = action->fwd.id;
2669 /* Add default rule to table */
2670 status = rte_pipeline_table_default_entry_add(p->p,
2679 /* Write response */
2681 rsp->table_rule_add_default.data = data_out;
2686 static struct pipeline_msg_rsp *
2687 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2688 struct pipeline_msg_req *req)
2690 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2692 uint32_t table_id = req->id;
2693 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2694 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2695 struct rte_pipeline_table_entry **data =
2696 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2697 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2698 uint32_t bulk = req->table_rule_add_bulk.bulk;
2700 struct rte_table_action *a = p->table_data[table_id].a;
2701 union table_rule_match_low_level *match_ll;
2703 void **match_ll_ptr;
2704 struct rte_pipeline_table_entry **action_ll_ptr;
2708 /* Memory allocation */
2709 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2710 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2711 match_ll_ptr = calloc(n_rules, sizeof(void *));
2713 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2714 found = calloc(n_rules, sizeof(int));
2716 if (match_ll == NULL ||
2717 action_ll == NULL ||
2718 match_ll_ptr == NULL ||
2719 action_ll_ptr == NULL ||
2723 for (i = 0; i < n_rules; i++) {
2724 match_ll_ptr[i] = (void *)&match_ll[i];
2726 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2729 /* Rule match conversion */
2730 for (i = 0; i < n_rules; i++) {
2731 status = match_convert(&match[i], match_ll_ptr[i], 1);
2736 /* Rule action conversion */
2737 for (i = 0; i < n_rules; i++) {
2738 status = action_convert(a, &action[i], action_ll_ptr[i]);
2743 /* Add rule (match, action) to table */
2745 status = rte_pipeline_table_entry_add_bulk(p->p,
2755 for (i = 0; i < n_rules; i++) {
2756 status = rte_pipeline_table_entry_add(p->p,
2769 /* Write response */
2771 rsp->table_rule_add_bulk.n_rules = n_rules;
2775 free(action_ll_ptr);
2784 free(action_ll_ptr);
2790 rsp->table_rule_add_bulk.n_rules = 0;
2794 static struct pipeline_msg_rsp *
2795 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2796 struct pipeline_msg_req *req)
2798 union table_rule_match_low_level match_ll;
2799 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2800 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2801 uint32_t table_id = req->id;
2802 int key_found, status;
2804 status = match_convert(match, &match_ll, 0);
2810 rsp->status = rte_pipeline_table_entry_delete(p->p,
2819 static struct pipeline_msg_rsp *
2820 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2821 struct pipeline_msg_req *req)
2823 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2824 uint32_t table_id = req->id;
2826 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2833 static struct pipeline_msg_rsp *
2834 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2835 struct pipeline_msg_req *req)
2837 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2838 uint32_t table_id = req->id;
2839 void *data = req->table_rule_stats_read.data;
2840 int clear = req->table_rule_stats_read.clear;
2841 struct rte_table_action *a = p->table_data[table_id].a;
2843 rsp->status = rte_table_action_stats_read(a,
2845 &rsp->table_rule_stats_read.stats,
2851 static struct pipeline_msg_rsp *
2852 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2853 struct pipeline_msg_req *req)
2855 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2856 uint32_t table_id = req->id;
2857 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2858 struct rte_table_action_meter_profile *profile =
2859 &req->table_mtr_profile_add.profile;
2860 struct rte_table_action *a = p->table_data[table_id].a;
2862 rsp->status = rte_table_action_meter_profile_add(a,
2869 static struct pipeline_msg_rsp *
2870 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2871 struct pipeline_msg_req *req)
2873 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2874 uint32_t table_id = req->id;
2875 uint32_t meter_profile_id =
2876 req->table_mtr_profile_delete.meter_profile_id;
2877 struct rte_table_action *a = p->table_data[table_id].a;
2879 rsp->status = rte_table_action_meter_profile_delete(a,
2885 static struct pipeline_msg_rsp *
2886 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2887 struct pipeline_msg_req *req)
2889 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2890 uint32_t table_id = req->id;
2891 void *data = req->table_rule_mtr_read.data;
2892 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2893 int clear = req->table_rule_mtr_read.clear;
2894 struct rte_table_action *a = p->table_data[table_id].a;
2896 rsp->status = rte_table_action_meter_read(a,
2899 &rsp->table_rule_mtr_read.stats,
2905 static struct pipeline_msg_rsp *
2906 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2907 struct pipeline_msg_req *req)
2909 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2910 uint32_t table_id = req->id;
2911 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2912 struct rte_table_action_dscp_table *dscp_table =
2913 &req->table_dscp_table_update.dscp_table;
2914 struct rte_table_action *a = p->table_data[table_id].a;
2916 rsp->status = rte_table_action_dscp_table_update(a,
2923 static struct pipeline_msg_rsp *
2924 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2925 struct pipeline_msg_req *req)
2927 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2928 uint32_t table_id = req->id;
2929 void *data = req->table_rule_ttl_read.data;
2930 int clear = req->table_rule_ttl_read.clear;
2931 struct rte_table_action *a = p->table_data[table_id].a;
2933 rsp->status = rte_table_action_ttl_read(a,
2935 &rsp->table_rule_ttl_read.stats,
2942 pipeline_msg_handle(struct pipeline_data *p)
2945 struct pipeline_msg_req *req;
2946 struct pipeline_msg_rsp *rsp;
2948 req = pipeline_msg_recv(p->msgq_req);
2952 switch (req->type) {
2953 case PIPELINE_REQ_PORT_IN_STATS_READ:
2954 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2957 case PIPELINE_REQ_PORT_IN_ENABLE:
2958 rsp = pipeline_msg_handle_port_in_enable(p, req);
2961 case PIPELINE_REQ_PORT_IN_DISABLE:
2962 rsp = pipeline_msg_handle_port_in_disable(p, req);
2965 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2966 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2969 case PIPELINE_REQ_TABLE_STATS_READ:
2970 rsp = pipeline_msg_handle_table_stats_read(p, req);
2973 case PIPELINE_REQ_TABLE_RULE_ADD:
2974 rsp = pipeline_msg_handle_table_rule_add(p, req);
2977 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2978 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2981 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2982 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2985 case PIPELINE_REQ_TABLE_RULE_DELETE:
2986 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2989 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2990 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2993 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2994 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
2997 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
2998 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
3001 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
3002 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
3005 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
3006 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
3009 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
3010 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
3013 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
3014 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
3018 rsp = (struct pipeline_msg_rsp *)req;
3022 pipeline_msg_send(p->msgq_rsp, rsp);
3027 * Data plane threads: main
3030 rte_pmd_softnic_run_internal(void *arg)
3032 struct rte_eth_dev *dev = arg;
3033 struct pmd_internals *softnic;
3034 struct softnic_thread_data *t;
3035 uint32_t thread_id, j;
3037 softnic = dev->data->dev_private;
3038 thread_id = rte_lcore_id();
3039 t = &softnic->thread_data[thread_id];
3043 for (j = 0; j < t->n_pipelines; j++)
3044 rte_pipeline_run(t->p[j]);
3047 if ((t->iter & 0xFLLU) == 0) {
3048 uint64_t time = rte_get_tsc_cycles();
3049 uint64_t time_next_min = UINT64_MAX;
3051 if (time < t->time_next_min)
3054 /* Pipeline message queues */
3055 for (j = 0; j < t->n_pipelines; j++) {
3056 struct pipeline_data *p =
3057 &t->pipeline_data[j];
3058 uint64_t time_next = p->time_next;
3060 if (time_next <= time) {
3061 pipeline_msg_handle(p);
3062 rte_pipeline_flush(p->p);
3063 time_next = time + p->timer_period;
3064 p->time_next = time_next;
3067 if (time_next < time_next_min)
3068 time_next_min = time_next;
3071 /* Thread message queues */
3073 uint64_t time_next = t->time_next;
3075 if (time_next <= time) {
3076 thread_msg_handle(t);
3077 time_next = time + t->timer_period;
3078 t->time_next = time_next;
3081 if (time_next < time_next_min)
3082 time_next_min = time_next;
3085 t->time_next_min = time_next_min;
3092 rte_pmd_softnic_run(uint16_t port_id)
3094 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3096 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
3097 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
3100 return (int)rte_pmd_softnic_run_internal(dev);