1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
7 #include <rte_common.h>
8 #include <rte_cycles.h>
10 #include <rte_service_component.h>
13 #include <rte_table_acl.h>
14 #include <rte_table_array.h>
15 #include <rte_table_hash.h>
16 #include <rte_table_lpm.h>
17 #include <rte_table_lpm_ipv6.h>
18 #include "rte_eth_softnic_internals.h"
21 * Master thread: data plane thread init
24 softnic_thread_free(struct pmd_internals *softnic)
28 RTE_LCORE_FOREACH_SLAVE(i) {
29 struct softnic_thread *t = &softnic->thread[i];
33 rte_ring_free(t->msgq_req);
36 rte_ring_free(t->msgq_rsp);
41 softnic_thread_init(struct pmd_internals *softnic)
45 for (i = 0; i < RTE_MAX_LCORE; i++) {
46 char ring_name[NAME_MAX];
47 struct rte_ring *msgq_req, *msgq_rsp;
48 struct softnic_thread *t = &softnic->thread[i];
49 struct softnic_thread_data *t_data = &softnic->thread_data[i];
50 uint32_t cpu_id = rte_lcore_to_socket_id(i);
53 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-REQ",
57 msgq_req = rte_ring_create(ring_name,
60 RING_F_SP_ENQ | RING_F_SC_DEQ);
62 if (msgq_req == NULL) {
63 softnic_thread_free(softnic);
67 snprintf(ring_name, sizeof(ring_name), "%s-TH%u-RSP",
71 msgq_rsp = rte_ring_create(ring_name,
74 RING_F_SP_ENQ | RING_F_SC_DEQ);
76 if (msgq_rsp == NULL) {
77 softnic_thread_free(softnic);
81 /* Master thread records */
82 t->msgq_req = msgq_req;
83 t->msgq_rsp = msgq_rsp;
84 t->service_id = UINT32_MAX;
86 /* Data plane thread records */
87 t_data->n_pipelines = 0;
88 t_data->msgq_req = msgq_req;
89 t_data->msgq_rsp = msgq_rsp;
90 t_data->timer_period =
91 (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
92 t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
93 t_data->time_next_min = t_data->time_next;
100 thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id)
102 struct rte_config *cfg = rte_eal_get_configuration();
103 enum rte_lcore_role_t role;
105 if ((thread_id >= RTE_MAX_LCORE) ||
106 (thread_id == cfg->master_lcore))
107 return 0; /* FALSE */
109 role = cfg->lcore_role[thread_id];
111 if ((softnic->params.sc && (role == ROLE_SERVICE)) ||
112 (!softnic->params.sc && (role == ROLE_RTE)))
115 return 0; /* FALSE */
119 thread_is_running(uint32_t thread_id)
121 enum rte_lcore_state_t thread_state;
123 thread_state = rte_eal_get_lcore_state(thread_id);
124 return (thread_state == RUNNING)? 1 : 0;
128 rte_pmd_softnic_run_internal(void *arg);
131 thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
133 struct rte_service_spec service_params;
134 struct softnic_thread *t = &softnic->thread[thread_id];
135 struct rte_eth_dev *dev;
140 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
144 dev = &rte_eth_devices[port_id];
145 snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
146 softnic->params.name,
148 service_params.callback = rte_pmd_softnic_run_internal;
149 service_params.callback_userdata = dev;
150 service_params.capabilities = 0;
151 service_params.socket_id = (int)softnic->params.cpu_id;
153 /* service register */
154 status = rte_service_component_register(&service_params, &t->service_id);
158 status = rte_service_component_runstate_set(t->service_id, 1);
160 rte_service_component_unregister(t->service_id);
161 t->service_id = UINT32_MAX;
165 status = rte_service_runstate_set(t->service_id, 1);
167 rte_service_component_runstate_set(t->service_id, 0);
168 rte_service_component_unregister(t->service_id);
169 t->service_id = UINT32_MAX;
173 /* service map to thread */
174 status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
176 rte_service_runstate_set(t->service_id, 0);
177 rte_service_component_runstate_set(t->service_id, 0);
178 rte_service_component_unregister(t->service_id);
179 t->service_id = UINT32_MAX;
187 thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
189 struct softnic_thread *t = &softnic->thread[thread_id];
191 /* service unmap from thread */
192 rte_service_map_lcore_set(t->service_id, thread_id, 0);
194 /* service unregister */
195 rte_service_runstate_set(t->service_id, 0);
196 rte_service_component_runstate_set(t->service_id, 0);
197 rte_service_component_unregister(t->service_id);
199 t->service_id = UINT32_MAX;
203 * Pipeline is running when:
204 * (A) Pipeline is mapped to a data plane thread AND
205 * (B) Its data plane thread is in RUNNING state.
208 pipeline_is_running(struct pipeline *p)
213 return thread_is_running(p->thread_id);
217 * Master thread & data plane threads: message passing
219 enum thread_req_type {
220 THREAD_REQ_PIPELINE_ENABLE = 0,
221 THREAD_REQ_PIPELINE_DISABLE,
225 struct thread_msg_req {
226 enum thread_req_type type;
230 struct rte_pipeline *p;
232 struct rte_table_action *a;
233 } table[RTE_PIPELINE_TABLE_MAX];
234 struct rte_ring *msgq_req;
235 struct rte_ring *msgq_rsp;
236 uint32_t timer_period_ms;
241 struct rte_pipeline *p;
246 struct thread_msg_rsp {
253 static struct thread_msg_req *
254 thread_msg_alloc(void)
256 size_t size = RTE_MAX(sizeof(struct thread_msg_req),
257 sizeof(struct thread_msg_rsp));
259 return calloc(1, size);
263 thread_msg_free(struct thread_msg_rsp *rsp)
268 static struct thread_msg_rsp *
269 thread_msg_send_recv(struct pmd_internals *softnic,
271 struct thread_msg_req *req)
273 struct softnic_thread *t = &softnic->thread[thread_id];
274 struct rte_ring *msgq_req = t->msgq_req;
275 struct rte_ring *msgq_rsp = t->msgq_rsp;
276 struct thread_msg_rsp *rsp;
281 status = rte_ring_sp_enqueue(msgq_req, req);
282 } while (status == -ENOBUFS);
286 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
287 } while (status != 0);
293 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
295 const char *pipeline_name)
297 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
298 struct thread_msg_req *req;
299 struct thread_msg_rsp *rsp;
300 uint32_t n_pipelines, i;
303 /* Check input params */
304 if (!thread_is_valid(softnic, thread_id) ||
306 (p->n_ports_in == 0) ||
307 (p->n_ports_out == 0) ||
308 (p->n_tables == 0) ||
312 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
313 if (n_pipelines >= THREAD_PIPELINES_MAX)
316 if (softnic->params.sc && (n_pipelines == 0)) {
317 status = thread_sc_service_up(softnic, thread_id);
322 if (!thread_is_running(thread_id)) {
323 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
324 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
326 /* Data plane thread */
327 td->p[td->n_pipelines] = p->p;
330 for (i = 0; i < p->n_tables; i++)
331 tdp->table_data[i].a =
333 tdp->n_tables = p->n_tables;
335 tdp->msgq_req = p->msgq_req;
336 tdp->msgq_rsp = p->msgq_rsp;
337 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
338 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
343 p->thread_id = thread_id;
349 /* Allocate request */
350 req = thread_msg_alloc();
355 req->type = THREAD_REQ_PIPELINE_ENABLE;
356 req->pipeline_enable.p = p->p;
357 for (i = 0; i < p->n_tables; i++)
358 req->pipeline_enable.table[i].a =
360 req->pipeline_enable.msgq_req = p->msgq_req;
361 req->pipeline_enable.msgq_rsp = p->msgq_rsp;
362 req->pipeline_enable.timer_period_ms = p->timer_period_ms;
363 req->pipeline_enable.n_tables = p->n_tables;
365 /* Send request and wait for response */
366 rsp = thread_msg_send_recv(softnic, thread_id, req);
371 status = rsp->status;
374 thread_msg_free(rsp);
376 /* Request completion */
380 p->thread_id = thread_id;
387 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
389 const char *pipeline_name)
391 struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
392 struct thread_msg_req *req;
393 struct thread_msg_rsp *rsp;
394 uint32_t n_pipelines;
397 /* Check input params */
398 if (!thread_is_valid(softnic, thread_id) ||
400 (p->enabled && (p->thread_id != thread_id)))
406 if (!thread_is_running(thread_id)) {
407 struct softnic_thread_data *td = &softnic->thread_data[thread_id];
410 for (i = 0; i < td->n_pipelines; i++) {
411 struct pipeline_data *tdp = &td->pipeline_data[i];
416 /* Data plane thread */
417 if (i < td->n_pipelines - 1) {
418 struct rte_pipeline *pipeline_last =
419 td->p[td->n_pipelines - 1];
420 struct pipeline_data *tdp_last =
421 &td->pipeline_data[td->n_pipelines - 1];
423 td->p[i] = pipeline_last;
424 memcpy(tdp, tdp_last, sizeof(*tdp));
435 if (softnic->params.sc && (td->n_pipelines == 0))
436 thread_sc_service_down(softnic, thread_id);
441 /* Allocate request */
442 req = thread_msg_alloc();
447 req->type = THREAD_REQ_PIPELINE_DISABLE;
448 req->pipeline_disable.p = p->p;
450 /* Send request and wait for response */
451 rsp = thread_msg_send_recv(softnic, thread_id, req);
456 status = rsp->status;
459 thread_msg_free(rsp);
461 /* Request completion */
467 n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
468 if (softnic->params.sc && (n_pipelines == 0))
469 thread_sc_service_down(softnic, thread_id);
475 * Data plane threads: message handling
477 static inline struct thread_msg_req *
478 thread_msg_recv(struct rte_ring *msgq_req)
480 struct thread_msg_req *req;
482 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
491 thread_msg_send(struct rte_ring *msgq_rsp,
492 struct thread_msg_rsp *rsp)
497 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
498 } while (status == -ENOBUFS);
501 static struct thread_msg_rsp *
502 thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
503 struct thread_msg_req *req)
505 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
506 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
510 t->p[t->n_pipelines] = req->pipeline_enable.p;
512 p->p = req->pipeline_enable.p;
513 for (i = 0; i < req->pipeline_enable.n_tables; i++)
515 req->pipeline_enable.table[i].a;
517 p->n_tables = req->pipeline_enable.n_tables;
519 p->msgq_req = req->pipeline_enable.msgq_req;
520 p->msgq_rsp = req->pipeline_enable.msgq_rsp;
522 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
523 p->time_next = rte_get_tsc_cycles() + p->timer_period;
532 static struct thread_msg_rsp *
533 thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
534 struct thread_msg_req *req)
536 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
537 uint32_t n_pipelines = t->n_pipelines;
538 struct rte_pipeline *pipeline = req->pipeline_disable.p;
542 for (i = 0; i < n_pipelines; i++) {
543 struct pipeline_data *p = &t->pipeline_data[i];
545 if (p->p != pipeline)
548 if (i < n_pipelines - 1) {
549 struct rte_pipeline *pipeline_last =
550 t->p[n_pipelines - 1];
551 struct pipeline_data *p_last =
552 &t->pipeline_data[n_pipelines - 1];
554 t->p[i] = pipeline_last;
555 memcpy(p, p_last, sizeof(*p));
564 /* should not get here */
570 thread_msg_handle(struct softnic_thread_data *t)
573 struct thread_msg_req *req;
574 struct thread_msg_rsp *rsp;
576 req = thread_msg_recv(t->msgq_req);
581 case THREAD_REQ_PIPELINE_ENABLE:
582 rsp = thread_msg_handle_pipeline_enable(t, req);
585 case THREAD_REQ_PIPELINE_DISABLE:
586 rsp = thread_msg_handle_pipeline_disable(t, req);
590 rsp = (struct thread_msg_rsp *)req;
594 thread_msg_send(t->msgq_rsp, rsp);
599 * Master thread & data plane threads: message passing
601 enum pipeline_req_type {
603 PIPELINE_REQ_PORT_IN_STATS_READ,
604 PIPELINE_REQ_PORT_IN_ENABLE,
605 PIPELINE_REQ_PORT_IN_DISABLE,
608 PIPELINE_REQ_PORT_OUT_STATS_READ,
611 PIPELINE_REQ_TABLE_STATS_READ,
612 PIPELINE_REQ_TABLE_RULE_ADD,
613 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
614 PIPELINE_REQ_TABLE_RULE_ADD_BULK,
615 PIPELINE_REQ_TABLE_RULE_DELETE,
616 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
617 PIPELINE_REQ_TABLE_RULE_STATS_READ,
618 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
619 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
620 PIPELINE_REQ_TABLE_RULE_MTR_READ,
621 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
622 PIPELINE_REQ_TABLE_RULE_TTL_READ,
626 struct pipeline_msg_req_port_in_stats_read {
630 struct pipeline_msg_req_port_out_stats_read {
634 struct pipeline_msg_req_table_stats_read {
638 struct pipeline_msg_req_table_rule_add {
639 struct softnic_table_rule_match match;
640 struct softnic_table_rule_action action;
643 struct pipeline_msg_req_table_rule_add_default {
644 struct softnic_table_rule_action action;
647 struct pipeline_msg_req_table_rule_add_bulk {
648 struct softnic_table_rule_match *match;
649 struct softnic_table_rule_action *action;
655 struct pipeline_msg_req_table_rule_delete {
656 struct softnic_table_rule_match match;
659 struct pipeline_msg_req_table_rule_stats_read {
664 struct pipeline_msg_req_table_mtr_profile_add {
665 uint32_t meter_profile_id;
666 struct rte_table_action_meter_profile profile;
669 struct pipeline_msg_req_table_mtr_profile_delete {
670 uint32_t meter_profile_id;
673 struct pipeline_msg_req_table_rule_mtr_read {
679 struct pipeline_msg_req_table_dscp_table_update {
681 struct rte_table_action_dscp_table dscp_table;
684 struct pipeline_msg_req_table_rule_ttl_read {
689 struct pipeline_msg_req {
690 enum pipeline_req_type type;
691 uint32_t id; /* Port IN, port OUT or table ID */
695 struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
696 struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
697 struct pipeline_msg_req_table_stats_read table_stats_read;
698 struct pipeline_msg_req_table_rule_add table_rule_add;
699 struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
700 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
701 struct pipeline_msg_req_table_rule_delete table_rule_delete;
702 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
703 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
704 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
705 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
706 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
707 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
711 struct pipeline_msg_rsp_port_in_stats_read {
712 struct rte_pipeline_port_in_stats stats;
715 struct pipeline_msg_rsp_port_out_stats_read {
716 struct rte_pipeline_port_out_stats stats;
719 struct pipeline_msg_rsp_table_stats_read {
720 struct rte_pipeline_table_stats stats;
723 struct pipeline_msg_rsp_table_rule_add {
727 struct pipeline_msg_rsp_table_rule_add_default {
731 struct pipeline_msg_rsp_table_rule_add_bulk {
735 struct pipeline_msg_rsp_table_rule_stats_read {
736 struct rte_table_action_stats_counters stats;
739 struct pipeline_msg_rsp_table_rule_mtr_read {
740 struct rte_table_action_mtr_counters stats;
743 struct pipeline_msg_rsp_table_rule_ttl_read {
744 struct rte_table_action_ttl_counters stats;
747 struct pipeline_msg_rsp {
752 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
753 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
754 struct pipeline_msg_rsp_table_stats_read table_stats_read;
755 struct pipeline_msg_rsp_table_rule_add table_rule_add;
756 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
757 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
758 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
759 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
760 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
767 static struct pipeline_msg_req *
768 pipeline_msg_alloc(void)
770 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
771 sizeof(struct pipeline_msg_rsp));
773 return calloc(1, size);
777 pipeline_msg_free(struct pipeline_msg_rsp *rsp)
782 static struct pipeline_msg_rsp *
783 pipeline_msg_send_recv(struct pipeline *p,
784 struct pipeline_msg_req *req)
786 struct rte_ring *msgq_req = p->msgq_req;
787 struct rte_ring *msgq_rsp = p->msgq_rsp;
788 struct pipeline_msg_rsp *rsp;
793 status = rte_ring_sp_enqueue(msgq_req, req);
794 } while (status == -ENOBUFS);
798 status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
799 } while (status != 0);
805 softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
806 const char *pipeline_name,
808 struct rte_pipeline_port_in_stats *stats,
812 struct pipeline_msg_req *req;
813 struct pipeline_msg_rsp *rsp;
816 /* Check input params */
817 if (pipeline_name == NULL ||
821 p = softnic_pipeline_find(softnic, pipeline_name);
823 port_id >= p->n_ports_in)
826 if (!pipeline_is_running(p)) {
827 status = rte_pipeline_port_in_stats_read(p->p,
835 /* Allocate request */
836 req = pipeline_msg_alloc();
841 req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
843 req->port_in_stats_read.clear = clear;
845 /* Send request and wait for response */
846 rsp = pipeline_msg_send_recv(p, req);
851 status = rsp->status;
853 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
856 pipeline_msg_free(rsp);
862 softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
863 const char *pipeline_name,
867 struct pipeline_msg_req *req;
868 struct pipeline_msg_rsp *rsp;
871 /* Check input params */
872 if (pipeline_name == NULL)
875 p = softnic_pipeline_find(softnic, pipeline_name);
877 port_id >= p->n_ports_in)
880 if (!pipeline_is_running(p)) {
881 status = rte_pipeline_port_in_enable(p->p, port_id);
885 /* Allocate request */
886 req = pipeline_msg_alloc();
891 req->type = PIPELINE_REQ_PORT_IN_ENABLE;
894 /* Send request and wait for response */
895 rsp = pipeline_msg_send_recv(p, req);
900 status = rsp->status;
903 pipeline_msg_free(rsp);
909 softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
910 const char *pipeline_name,
914 struct pipeline_msg_req *req;
915 struct pipeline_msg_rsp *rsp;
918 /* Check input params */
919 if (pipeline_name == NULL)
922 p = softnic_pipeline_find(softnic, pipeline_name);
924 port_id >= p->n_ports_in)
927 if (!pipeline_is_running(p)) {
928 status = rte_pipeline_port_in_disable(p->p, port_id);
932 /* Allocate request */
933 req = pipeline_msg_alloc();
938 req->type = PIPELINE_REQ_PORT_IN_DISABLE;
941 /* Send request and wait for response */
942 rsp = pipeline_msg_send_recv(p, req);
947 status = rsp->status;
950 pipeline_msg_free(rsp);
956 softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
957 const char *pipeline_name,
959 struct rte_pipeline_port_out_stats *stats,
963 struct pipeline_msg_req *req;
964 struct pipeline_msg_rsp *rsp;
967 /* Check input params */
968 if (pipeline_name == NULL ||
972 p = softnic_pipeline_find(softnic, pipeline_name);
974 port_id >= p->n_ports_out)
977 if (!pipeline_is_running(p)) {
978 status = rte_pipeline_port_out_stats_read(p->p,
986 /* Allocate request */
987 req = pipeline_msg_alloc();
992 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
994 req->port_out_stats_read.clear = clear;
996 /* Send request and wait for response */
997 rsp = pipeline_msg_send_recv(p, req);
1002 status = rsp->status;
1004 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
1007 pipeline_msg_free(rsp);
1013 softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
1014 const char *pipeline_name,
1016 struct rte_pipeline_table_stats *stats,
1020 struct pipeline_msg_req *req;
1021 struct pipeline_msg_rsp *rsp;
1024 /* Check input params */
1025 if (pipeline_name == NULL ||
1029 p = softnic_pipeline_find(softnic, pipeline_name);
1031 table_id >= p->n_tables)
1034 if (!pipeline_is_running(p)) {
1035 status = rte_pipeline_table_stats_read(p->p,
1043 /* Allocate request */
1044 req = pipeline_msg_alloc();
1049 req->type = PIPELINE_REQ_TABLE_STATS_READ;
1051 req->table_stats_read.clear = clear;
1053 /* Send request and wait for response */
1054 rsp = pipeline_msg_send_recv(p, req);
1059 status = rsp->status;
1061 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
1064 pipeline_msg_free(rsp);
1070 match_check(struct softnic_table_rule_match *match,
1074 struct softnic_table *table;
1076 if (match == NULL ||
1078 table_id >= p->n_tables)
1081 table = &p->table[table_id];
1082 if (match->match_type != table->params.match_type)
1085 switch (match->match_type) {
1088 struct softnic_table_acl_params *t = &table->params.match.acl;
1089 struct softnic_table_rule_match_acl *r = &match->match.acl;
1091 if ((r->ip_version && (t->ip_version == 0)) ||
1092 ((r->ip_version == 0) && t->ip_version))
1095 if (r->ip_version) {
1096 if (r->sa_depth > 32 ||
1100 if (r->sa_depth > 128 ||
1115 struct softnic_table_lpm_params *t = &table->params.match.lpm;
1116 struct softnic_table_rule_match_lpm *r = &match->match.lpm;
1118 if ((r->ip_version && (t->key_size != 4)) ||
1119 ((r->ip_version == 0) && (t->key_size != 16)))
1122 if (r->ip_version) {
1141 action_check(struct softnic_table_rule_action *action,
1145 struct softnic_table_action_profile *ap;
1147 if (action == NULL ||
1149 table_id >= p->n_tables)
1152 ap = p->table[table_id].ap;
1153 if (action->action_mask != ap->params.action_mask)
1156 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1157 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1158 action->fwd.id >= p->n_ports_out)
1161 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1162 action->fwd.id >= p->n_tables)
1166 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
1167 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
1168 uint32_t tc_mask1 = action->mtr.tc_mask;
1170 if (tc_mask1 != tc_mask0)
1174 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
1175 uint32_t n_subports_per_port =
1176 ap->params.tm.n_subports_per_port;
1177 uint32_t n_pipes_per_subport =
1178 ap->params.tm.n_pipes_per_subport;
1179 uint32_t subport_id = action->tm.subport_id;
1180 uint32_t pipe_id = action->tm.pipe_id;
1182 if (subport_id >= n_subports_per_port ||
1183 pipe_id >= n_pipes_per_subport)
1187 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
1188 uint64_t encap_mask = ap->params.encap.encap_mask;
1189 enum rte_table_action_encap_type type = action->encap.type;
1191 if ((encap_mask & (1LLU << type)) == 0)
1195 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
1196 int ip_version0 = ap->params.common.ip_version;
1197 int ip_version1 = action->nat.ip_version;
1199 if ((ip_version1 && (ip_version0 == 0)) ||
1200 ((ip_version1 == 0) && ip_version0))
1208 action_default_check(struct softnic_table_rule_action *action,
1212 if (action == NULL ||
1213 action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
1215 table_id >= p->n_tables)
1218 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
1219 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
1220 action->fwd.id >= p->n_ports_out)
1223 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
1224 action->fwd.id >= p->n_tables)
1231 union table_rule_match_low_level {
1232 struct rte_table_acl_rule_add_params acl_add;
1233 struct rte_table_acl_rule_delete_params acl_delete;
1234 struct rte_table_array_key array;
1235 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
1236 struct rte_table_lpm_key lpm_ipv4;
1237 struct rte_table_lpm_ipv6_key lpm_ipv6;
1241 match_convert(struct softnic_table_rule_match *mh,
1242 union table_rule_match_low_level *ml,
1246 action_convert(struct rte_table_action *a,
1247 struct softnic_table_rule_action *action,
1248 struct rte_pipeline_table_entry *data);
1251 softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
1252 const char *pipeline_name,
1254 struct softnic_table_rule_match *match,
1255 struct softnic_table_rule_action *action,
1259 struct pipeline_msg_req *req;
1260 struct pipeline_msg_rsp *rsp;
1263 /* Check input params */
1264 if (pipeline_name == NULL ||
1270 p = softnic_pipeline_find(softnic, pipeline_name);
1272 table_id >= p->n_tables ||
1273 match_check(match, p, table_id) ||
1274 action_check(action, p, table_id))
1277 if (!pipeline_is_running(p)) {
1278 struct rte_table_action *a = p->table[table_id].a;
1279 union table_rule_match_low_level match_ll;
1280 struct rte_pipeline_table_entry *data_in, *data_out;
1284 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1288 /* Table match-action rule conversion */
1289 data_in = (struct rte_pipeline_table_entry *)buffer;
1291 status = match_convert(match, &match_ll, 1);
1297 status = action_convert(a, action, data_in);
1303 /* Add rule (match, action) to table */
1304 status = rte_pipeline_table_entry_add(p->p,
1315 /* Write Response */
1322 /* Allocate request */
1323 req = pipeline_msg_alloc();
1328 req->type = PIPELINE_REQ_TABLE_RULE_ADD;
1330 memcpy(&req->table_rule_add.match, match, sizeof(*match));
1331 memcpy(&req->table_rule_add.action, action, sizeof(*action));
1333 /* Send request and wait for response */
1334 rsp = pipeline_msg_send_recv(p, req);
1339 status = rsp->status;
1341 *data = rsp->table_rule_add.data;
1344 pipeline_msg_free(rsp);
1350 softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
1351 const char *pipeline_name,
1353 struct softnic_table_rule_action *action,
1357 struct pipeline_msg_req *req;
1358 struct pipeline_msg_rsp *rsp;
1361 /* Check input params */
1362 if (pipeline_name == NULL ||
1367 p = softnic_pipeline_find(softnic, pipeline_name);
1369 table_id >= p->n_tables ||
1370 action_default_check(action, p, table_id))
1373 if (!pipeline_is_running(p)) {
1374 struct rte_pipeline_table_entry *data_in, *data_out;
1377 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
1382 data_in = (struct rte_pipeline_table_entry *)buffer;
1384 data_in->action = action->fwd.action;
1385 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
1386 data_in->port_id = action->fwd.id;
1387 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
1388 data_in->table_id = action->fwd.id;
1390 /* Add default rule to table */
1391 status = rte_pipeline_table_default_entry_add(p->p,
1400 /* Write Response */
1407 /* Allocate request */
1408 req = pipeline_msg_alloc();
1413 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
1415 memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
1417 /* Send request and wait for response */
1418 rsp = pipeline_msg_send_recv(p, req);
1423 status = rsp->status;
1425 *data = rsp->table_rule_add_default.data;
1428 pipeline_msg_free(rsp);
1434 softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
1435 const char *pipeline_name,
1437 struct softnic_table_rule_match *match,
1438 struct softnic_table_rule_action *action,
1443 struct pipeline_msg_req *req;
1444 struct pipeline_msg_rsp *rsp;
1448 /* Check input params */
1449 if (pipeline_name == NULL ||
1457 p = softnic_pipeline_find(softnic, pipeline_name);
1459 table_id >= p->n_tables)
1462 for (i = 0; i < *n_rules; i++)
1463 if (match_check(match, p, table_id) ||
1464 action_check(action, p, table_id))
1467 if (!pipeline_is_running(p)) {
1468 struct rte_table_action *a = p->table[table_id].a;
1469 union table_rule_match_low_level *match_ll;
1471 void **match_ll_ptr;
1472 struct rte_pipeline_table_entry **action_ll_ptr;
1473 struct rte_pipeline_table_entry **entries_ptr =
1474 (struct rte_pipeline_table_entry **)data;
1476 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1479 /* Memory allocation */
1480 match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
1481 action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
1482 match_ll_ptr = calloc(*n_rules, sizeof(void *));
1484 calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
1485 found = calloc(*n_rules, sizeof(int));
1487 if (match_ll == NULL ||
1488 action_ll == NULL ||
1489 match_ll_ptr == NULL ||
1490 action_ll_ptr == NULL ||
1494 for (i = 0; i < *n_rules; i++) {
1495 match_ll_ptr[i] = (void *)&match_ll[i];
1497 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
1500 /* Rule match conversion */
1501 for (i = 0; i < *n_rules; i++) {
1502 status = match_convert(&match[i], match_ll_ptr[i], 1);
1507 /* Rule action conversion */
1508 for (i = 0; i < *n_rules; i++) {
1509 status = action_convert(a, &action[i], action_ll_ptr[i]);
1514 /* Add rule (match, action) to table */
1516 status = rte_pipeline_table_entry_add_bulk(p->p,
1526 for (i = 0; i < *n_rules; i++) {
1527 status = rte_pipeline_table_entry_add(p->p,
1542 free(action_ll_ptr);
1551 free(action_ll_ptr);
1560 /* Allocate request */
1561 req = pipeline_msg_alloc();
1566 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
1568 req->table_rule_add_bulk.match = match;
1569 req->table_rule_add_bulk.action = action;
1570 req->table_rule_add_bulk.data = data;
1571 req->table_rule_add_bulk.n_rules = *n_rules;
1572 req->table_rule_add_bulk.bulk =
1573 (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
1575 /* Send request and wait for response */
1576 rsp = pipeline_msg_send_recv(p, req);
1581 status = rsp->status;
1583 *n_rules = rsp->table_rule_add_bulk.n_rules;
1586 pipeline_msg_free(rsp);
1592 softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
1593 const char *pipeline_name,
1595 struct softnic_table_rule_match *match)
1598 struct pipeline_msg_req *req;
1599 struct pipeline_msg_rsp *rsp;
1602 /* Check input params */
1603 if (pipeline_name == NULL ||
1607 p = softnic_pipeline_find(softnic, pipeline_name);
1609 table_id >= p->n_tables ||
1610 match_check(match, p, table_id))
1613 if (!pipeline_is_running(p)) {
1614 union table_rule_match_low_level match_ll;
1617 status = match_convert(match, &match_ll, 0);
1621 status = rte_pipeline_table_entry_delete(p->p,
1630 /* Allocate request */
1631 req = pipeline_msg_alloc();
1636 req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
1638 memcpy(&req->table_rule_delete.match, match, sizeof(*match));
1640 /* Send request and wait for response */
1641 rsp = pipeline_msg_send_recv(p, req);
1646 status = rsp->status;
1649 pipeline_msg_free(rsp);
1655 softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
1656 const char *pipeline_name,
1660 struct pipeline_msg_req *req;
1661 struct pipeline_msg_rsp *rsp;
1664 /* Check input params */
1665 if (pipeline_name == NULL)
1668 p = softnic_pipeline_find(softnic, pipeline_name);
1670 table_id >= p->n_tables)
1673 if (!pipeline_is_running(p)) {
1674 status = rte_pipeline_table_default_entry_delete(p->p,
1681 /* Allocate request */
1682 req = pipeline_msg_alloc();
1687 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
1690 /* Send request and wait for response */
1691 rsp = pipeline_msg_send_recv(p, req);
1696 status = rsp->status;
1699 pipeline_msg_free(rsp);
1705 softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
1706 const char *pipeline_name,
1709 struct rte_table_action_stats_counters *stats,
1713 struct pipeline_msg_req *req;
1714 struct pipeline_msg_rsp *rsp;
1717 /* Check input params */
1718 if (pipeline_name == NULL ||
1723 p = softnic_pipeline_find(softnic, pipeline_name);
1725 table_id >= p->n_tables)
1728 if (!pipeline_is_running(p)) {
1729 struct rte_table_action *a = p->table[table_id].a;
1731 status = rte_table_action_stats_read(a,
1739 /* Allocate request */
1740 req = pipeline_msg_alloc();
1745 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
1747 req->table_rule_stats_read.data = data;
1748 req->table_rule_stats_read.clear = clear;
1750 /* Send request and wait for response */
1751 rsp = pipeline_msg_send_recv(p, req);
1756 status = rsp->status;
1758 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
1761 pipeline_msg_free(rsp);
1767 softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
1768 const char *pipeline_name,
1770 uint32_t meter_profile_id,
1771 struct rte_table_action_meter_profile *profile)
1774 struct pipeline_msg_req *req;
1775 struct pipeline_msg_rsp *rsp;
1776 struct softnic_table *table;
1777 struct softnic_table_meter_profile *mp;
1780 /* Check input params */
1781 if (pipeline_name == NULL ||
1785 p = softnic_pipeline_find(softnic, pipeline_name);
1787 table_id >= p->n_tables)
1790 table = &p->table[table_id];
1791 mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
1795 /* Resource Allocation */
1796 mp = calloc(1, sizeof(struct softnic_table_meter_profile));
1800 mp->meter_profile_id = meter_profile_id;
1801 memcpy(&mp->profile, profile, sizeof(mp->profile));
1803 if (!pipeline_is_running(p)) {
1804 status = rte_table_action_meter_profile_add(table->a,
1812 /* Add profile to the table. */
1813 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1818 /* Allocate request */
1819 req = pipeline_msg_alloc();
1826 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
1828 req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
1829 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
1831 /* Send request and wait for response */
1832 rsp = pipeline_msg_send_recv(p, req);
1839 status = rsp->status;
1841 TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
1846 pipeline_msg_free(rsp);
1852 softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
1853 const char *pipeline_name,
1855 uint32_t meter_profile_id)
1858 struct pipeline_msg_req *req;
1859 struct pipeline_msg_rsp *rsp;
1862 /* Check input params */
1863 if (pipeline_name == NULL)
1866 p = softnic_pipeline_find(softnic, pipeline_name);
1868 table_id >= p->n_tables)
1871 if (!pipeline_is_running(p)) {
1872 struct rte_table_action *a = p->table[table_id].a;
1874 status = rte_table_action_meter_profile_delete(a,
1880 /* Allocate request */
1881 req = pipeline_msg_alloc();
1886 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
1888 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
1890 /* Send request and wait for response */
1891 rsp = pipeline_msg_send_recv(p, req);
1896 status = rsp->status;
1899 pipeline_msg_free(rsp);
1905 softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
1906 const char *pipeline_name,
1910 struct rte_table_action_mtr_counters *stats,
1914 struct pipeline_msg_req *req;
1915 struct pipeline_msg_rsp *rsp;
1918 /* Check input params */
1919 if (pipeline_name == NULL ||
1924 p = softnic_pipeline_find(softnic, pipeline_name);
1926 table_id >= p->n_tables)
1929 if (!pipeline_is_running(p)) {
1930 struct rte_table_action *a = p->table[table_id].a;
1932 status = rte_table_action_meter_read(a,
1941 /* Allocate request */
1942 req = pipeline_msg_alloc();
1947 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
1949 req->table_rule_mtr_read.data = data;
1950 req->table_rule_mtr_read.tc_mask = tc_mask;
1951 req->table_rule_mtr_read.clear = clear;
1953 /* Send request and wait for response */
1954 rsp = pipeline_msg_send_recv(p, req);
1959 status = rsp->status;
1961 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
1964 pipeline_msg_free(rsp);
1970 softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
1971 const char *pipeline_name,
1974 struct rte_table_action_dscp_table *dscp_table)
1977 struct pipeline_msg_req *req;
1978 struct pipeline_msg_rsp *rsp;
1981 /* Check input params */
1982 if (pipeline_name == NULL ||
1986 p = softnic_pipeline_find(softnic, pipeline_name);
1988 table_id >= p->n_tables)
1991 if (!pipeline_is_running(p)) {
1992 struct rte_table_action *a = p->table[table_id].a;
1994 status = rte_table_action_dscp_table_update(a,
1998 /* Update table dscp table */
2000 memcpy(&p->table[table_id].dscp_table, dscp_table,
2001 sizeof(p->table[table_id].dscp_table));
2006 /* Allocate request */
2007 req = pipeline_msg_alloc();
2012 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
2014 req->table_dscp_table_update.dscp_mask = dscp_mask;
2015 memcpy(&req->table_dscp_table_update.dscp_table,
2016 dscp_table, sizeof(*dscp_table));
2018 /* Send request and wait for response */
2019 rsp = pipeline_msg_send_recv(p, req);
2024 status = rsp->status;
2026 /* Update table dscp table */
2028 memcpy(&p->table[table_id].dscp_table, dscp_table,
2029 sizeof(p->table[table_id].dscp_table));
2032 pipeline_msg_free(rsp);
2038 softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
2039 const char *pipeline_name,
2042 struct rte_table_action_ttl_counters *stats,
2046 struct pipeline_msg_req *req;
2047 struct pipeline_msg_rsp *rsp;
2050 /* Check input params */
2051 if (pipeline_name == NULL ||
2056 p = softnic_pipeline_find(softnic, pipeline_name);
2058 table_id >= p->n_tables)
2061 if (!pipeline_is_running(p)) {
2062 struct rte_table_action *a = p->table[table_id].a;
2064 status = rte_table_action_ttl_read(a,
2072 /* Allocate request */
2073 req = pipeline_msg_alloc();
2078 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
2080 req->table_rule_ttl_read.data = data;
2081 req->table_rule_ttl_read.clear = clear;
2083 /* Send request and wait for response */
2084 rsp = pipeline_msg_send_recv(p, req);
2089 status = rsp->status;
2091 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
2094 pipeline_msg_free(rsp);
2100 * Data plane threads: message handling
2102 static inline struct pipeline_msg_req *
2103 pipeline_msg_recv(struct rte_ring *msgq_req)
2105 struct pipeline_msg_req *req;
2107 int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
2116 pipeline_msg_send(struct rte_ring *msgq_rsp,
2117 struct pipeline_msg_rsp *rsp)
2122 status = rte_ring_sp_enqueue(msgq_rsp, rsp);
2123 } while (status == -ENOBUFS);
2126 static struct pipeline_msg_rsp *
2127 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
2128 struct pipeline_msg_req *req)
2130 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2131 uint32_t port_id = req->id;
2132 int clear = req->port_in_stats_read.clear;
2134 rsp->status = rte_pipeline_port_in_stats_read(p->p,
2136 &rsp->port_in_stats_read.stats,
2142 static struct pipeline_msg_rsp *
2143 pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
2144 struct pipeline_msg_req *req)
2146 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2147 uint32_t port_id = req->id;
2149 rsp->status = rte_pipeline_port_in_enable(p->p,
2155 static struct pipeline_msg_rsp *
2156 pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
2157 struct pipeline_msg_req *req)
2159 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2160 uint32_t port_id = req->id;
2162 rsp->status = rte_pipeline_port_in_disable(p->p,
2168 static struct pipeline_msg_rsp *
2169 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
2170 struct pipeline_msg_req *req)
2172 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2173 uint32_t port_id = req->id;
2174 int clear = req->port_out_stats_read.clear;
2176 rsp->status = rte_pipeline_port_out_stats_read(p->p,
2178 &rsp->port_out_stats_read.stats,
2184 static struct pipeline_msg_rsp *
2185 pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
2186 struct pipeline_msg_req *req)
2188 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2189 uint32_t port_id = req->id;
2190 int clear = req->table_stats_read.clear;
2192 rsp->status = rte_pipeline_table_stats_read(p->p,
2194 &rsp->table_stats_read.stats,
2201 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
2206 switch (depth / 32) {
2216 depth32[1] = depth - 32;
2224 depth32[2] = depth - 64;
2232 depth32[3] = depth - 96;
2248 match_convert(struct softnic_table_rule_match *mh,
2249 union table_rule_match_low_level *ml,
2252 memset(ml, 0, sizeof(*ml));
2254 switch (mh->match_type) {
2256 if (mh->match.acl.ip_version)
2258 ml->acl_add.field_value[0].value.u8 =
2259 mh->match.acl.proto;
2260 ml->acl_add.field_value[0].mask_range.u8 =
2261 mh->match.acl.proto_mask;
2263 ml->acl_add.field_value[1].value.u32 =
2264 mh->match.acl.ipv4.sa;
2265 ml->acl_add.field_value[1].mask_range.u32 =
2266 mh->match.acl.sa_depth;
2268 ml->acl_add.field_value[2].value.u32 =
2269 mh->match.acl.ipv4.da;
2270 ml->acl_add.field_value[2].mask_range.u32 =
2271 mh->match.acl.da_depth;
2273 ml->acl_add.field_value[3].value.u16 =
2275 ml->acl_add.field_value[3].mask_range.u16 =
2278 ml->acl_add.field_value[4].value.u16 =
2280 ml->acl_add.field_value[4].mask_range.u16 =
2283 ml->acl_add.priority =
2284 (int32_t)mh->match.acl.priority;
2286 ml->acl_delete.field_value[0].value.u8 =
2287 mh->match.acl.proto;
2288 ml->acl_delete.field_value[0].mask_range.u8 =
2289 mh->match.acl.proto_mask;
2291 ml->acl_delete.field_value[1].value.u32 =
2292 mh->match.acl.ipv4.sa;
2293 ml->acl_delete.field_value[1].mask_range.u32 =
2294 mh->match.acl.sa_depth;
2296 ml->acl_delete.field_value[2].value.u32 =
2297 mh->match.acl.ipv4.da;
2298 ml->acl_delete.field_value[2].mask_range.u32 =
2299 mh->match.acl.da_depth;
2301 ml->acl_delete.field_value[3].value.u16 =
2303 ml->acl_delete.field_value[3].mask_range.u16 =
2306 ml->acl_delete.field_value[4].value.u16 =
2308 ml->acl_delete.field_value[4].mask_range.u16 =
2314 (uint32_t *)mh->match.acl.ipv6.sa;
2316 (uint32_t *)mh->match.acl.ipv6.da;
2317 uint32_t sa32_depth[4], da32_depth[4];
2320 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2325 status = match_convert_ipv6_depth(
2326 mh->match.acl.da_depth,
2331 ml->acl_add.field_value[0].value.u8 =
2332 mh->match.acl.proto;
2333 ml->acl_add.field_value[0].mask_range.u8 =
2334 mh->match.acl.proto_mask;
2336 ml->acl_add.field_value[1].value.u32 =
2337 rte_be_to_cpu_32(sa32[0]);
2338 ml->acl_add.field_value[1].mask_range.u32 =
2340 ml->acl_add.field_value[2].value.u32 =
2341 rte_be_to_cpu_32(sa32[1]);
2342 ml->acl_add.field_value[2].mask_range.u32 =
2344 ml->acl_add.field_value[3].value.u32 =
2345 rte_be_to_cpu_32(sa32[2]);
2346 ml->acl_add.field_value[3].mask_range.u32 =
2348 ml->acl_add.field_value[4].value.u32 =
2349 rte_be_to_cpu_32(sa32[3]);
2350 ml->acl_add.field_value[4].mask_range.u32 =
2353 ml->acl_add.field_value[5].value.u32 =
2354 rte_be_to_cpu_32(da32[0]);
2355 ml->acl_add.field_value[5].mask_range.u32 =
2357 ml->acl_add.field_value[6].value.u32 =
2358 rte_be_to_cpu_32(da32[1]);
2359 ml->acl_add.field_value[6].mask_range.u32 =
2361 ml->acl_add.field_value[7].value.u32 =
2362 rte_be_to_cpu_32(da32[2]);
2363 ml->acl_add.field_value[7].mask_range.u32 =
2365 ml->acl_add.field_value[8].value.u32 =
2366 rte_be_to_cpu_32(da32[3]);
2367 ml->acl_add.field_value[8].mask_range.u32 =
2370 ml->acl_add.field_value[9].value.u16 =
2372 ml->acl_add.field_value[9].mask_range.u16 =
2375 ml->acl_add.field_value[10].value.u16 =
2377 ml->acl_add.field_value[10].mask_range.u16 =
2380 ml->acl_add.priority =
2381 (int32_t)mh->match.acl.priority;
2384 (uint32_t *)mh->match.acl.ipv6.sa;
2386 (uint32_t *)mh->match.acl.ipv6.da;
2387 uint32_t sa32_depth[4], da32_depth[4];
2390 status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
2395 status = match_convert_ipv6_depth(mh->match.acl.da_depth,
2400 ml->acl_delete.field_value[0].value.u8 =
2401 mh->match.acl.proto;
2402 ml->acl_delete.field_value[0].mask_range.u8 =
2403 mh->match.acl.proto_mask;
2405 ml->acl_delete.field_value[1].value.u32 =
2406 rte_be_to_cpu_32(sa32[0]);
2407 ml->acl_delete.field_value[1].mask_range.u32 =
2409 ml->acl_delete.field_value[2].value.u32 =
2410 rte_be_to_cpu_32(sa32[1]);
2411 ml->acl_delete.field_value[2].mask_range.u32 =
2413 ml->acl_delete.field_value[3].value.u32 =
2414 rte_be_to_cpu_32(sa32[2]);
2415 ml->acl_delete.field_value[3].mask_range.u32 =
2417 ml->acl_delete.field_value[4].value.u32 =
2418 rte_be_to_cpu_32(sa32[3]);
2419 ml->acl_delete.field_value[4].mask_range.u32 =
2422 ml->acl_delete.field_value[5].value.u32 =
2423 rte_be_to_cpu_32(da32[0]);
2424 ml->acl_delete.field_value[5].mask_range.u32 =
2426 ml->acl_delete.field_value[6].value.u32 =
2427 rte_be_to_cpu_32(da32[1]);
2428 ml->acl_delete.field_value[6].mask_range.u32 =
2430 ml->acl_delete.field_value[7].value.u32 =
2431 rte_be_to_cpu_32(da32[2]);
2432 ml->acl_delete.field_value[7].mask_range.u32 =
2434 ml->acl_delete.field_value[8].value.u32 =
2435 rte_be_to_cpu_32(da32[3]);
2436 ml->acl_delete.field_value[8].mask_range.u32 =
2439 ml->acl_delete.field_value[9].value.u16 =
2441 ml->acl_delete.field_value[9].mask_range.u16 =
2444 ml->acl_delete.field_value[10].value.u16 =
2446 ml->acl_delete.field_value[10].mask_range.u16 =
2452 ml->array.pos = mh->match.array.pos;
2456 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
2460 if (mh->match.lpm.ip_version) {
2461 ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
2462 ml->lpm_ipv4.depth = mh->match.lpm.depth;
2464 memcpy(ml->lpm_ipv6.ip,
2465 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
2466 ml->lpm_ipv6.depth = mh->match.lpm.depth;
2477 action_convert(struct rte_table_action *a,
2478 struct softnic_table_rule_action *action,
2479 struct rte_pipeline_table_entry *data)
2484 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
2485 status = rte_table_action_apply(a,
2487 RTE_TABLE_ACTION_FWD,
2494 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
2495 status = rte_table_action_apply(a,
2497 RTE_TABLE_ACTION_LB,
2504 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
2505 status = rte_table_action_apply(a,
2507 RTE_TABLE_ACTION_MTR,
2514 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
2515 status = rte_table_action_apply(a,
2517 RTE_TABLE_ACTION_TM,
2524 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
2525 status = rte_table_action_apply(a,
2527 RTE_TABLE_ACTION_ENCAP,
2534 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
2535 status = rte_table_action_apply(a,
2537 RTE_TABLE_ACTION_NAT,
2544 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
2545 status = rte_table_action_apply(a,
2547 RTE_TABLE_ACTION_TTL,
2554 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
2555 status = rte_table_action_apply(a,
2557 RTE_TABLE_ACTION_STATS,
2564 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
2565 status = rte_table_action_apply(a,
2567 RTE_TABLE_ACTION_TIME,
2574 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
2575 status = rte_table_action_apply(a,
2577 RTE_TABLE_ACTION_TAG,
2584 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
2585 status = rte_table_action_apply(a,
2587 RTE_TABLE_ACTION_DECAP,
2594 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
2595 status = rte_table_action_apply(a,
2597 RTE_TABLE_ACTION_SYM_CRYPTO,
2598 &action->sym_crypto);
2607 static struct pipeline_msg_rsp *
2608 pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
2609 struct pipeline_msg_req *req)
2611 union table_rule_match_low_level match_ll;
2612 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2613 struct softnic_table_rule_match *match = &req->table_rule_add.match;
2614 struct softnic_table_rule_action *action = &req->table_rule_add.action;
2615 struct rte_pipeline_table_entry *data_in, *data_out;
2616 uint32_t table_id = req->id;
2617 int key_found, status;
2618 struct rte_table_action *a = p->table_data[table_id].a;
2621 memset(p->buffer, 0, sizeof(p->buffer));
2622 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2624 status = match_convert(match, &match_ll, 1);
2630 status = action_convert(a, action, data_in);
2636 status = rte_pipeline_table_entry_add(p->p,
2647 /* Write response */
2649 rsp->table_rule_add.data = data_out;
2654 static struct pipeline_msg_rsp *
2655 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
2656 struct pipeline_msg_req *req)
2658 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2659 struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
2660 struct rte_pipeline_table_entry *data_in, *data_out;
2661 uint32_t table_id = req->id;
2665 memset(p->buffer, 0, sizeof(p->buffer));
2666 data_in = (struct rte_pipeline_table_entry *)p->buffer;
2668 data_in->action = action->fwd.action;
2669 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
2670 data_in->port_id = action->fwd.id;
2671 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
2672 data_in->table_id = action->fwd.id;
2674 /* Add default rule to table */
2675 status = rte_pipeline_table_default_entry_add(p->p,
2684 /* Write response */
2686 rsp->table_rule_add_default.data = data_out;
2691 static struct pipeline_msg_rsp *
2692 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
2693 struct pipeline_msg_req *req)
2695 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2697 uint32_t table_id = req->id;
2698 struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
2699 struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
2700 struct rte_pipeline_table_entry **data =
2701 (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
2702 uint32_t n_rules = req->table_rule_add_bulk.n_rules;
2703 uint32_t bulk = req->table_rule_add_bulk.bulk;
2705 struct rte_table_action *a = p->table_data[table_id].a;
2706 union table_rule_match_low_level *match_ll;
2708 void **match_ll_ptr;
2709 struct rte_pipeline_table_entry **action_ll_ptr;
2713 /* Memory allocation */
2714 match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
2715 action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
2716 match_ll_ptr = calloc(n_rules, sizeof(void *));
2718 calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
2719 found = calloc(n_rules, sizeof(int));
2721 if (match_ll == NULL ||
2722 action_ll == NULL ||
2723 match_ll_ptr == NULL ||
2724 action_ll_ptr == NULL ||
2728 for (i = 0; i < n_rules; i++) {
2729 match_ll_ptr[i] = (void *)&match_ll[i];
2731 (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
2734 /* Rule match conversion */
2735 for (i = 0; i < n_rules; i++) {
2736 status = match_convert(&match[i], match_ll_ptr[i], 1);
2741 /* Rule action conversion */
2742 for (i = 0; i < n_rules; i++) {
2743 status = action_convert(a, &action[i], action_ll_ptr[i]);
2748 /* Add rule (match, action) to table */
2750 status = rte_pipeline_table_entry_add_bulk(p->p,
2760 for (i = 0; i < n_rules; i++) {
2761 status = rte_pipeline_table_entry_add(p->p,
2774 /* Write response */
2776 rsp->table_rule_add_bulk.n_rules = n_rules;
2780 free(action_ll_ptr);
2789 free(action_ll_ptr);
2795 rsp->table_rule_add_bulk.n_rules = 0;
2799 static struct pipeline_msg_rsp *
2800 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
2801 struct pipeline_msg_req *req)
2803 union table_rule_match_low_level match_ll;
2804 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2805 struct softnic_table_rule_match *match = &req->table_rule_delete.match;
2806 uint32_t table_id = req->id;
2807 int key_found, status;
2809 status = match_convert(match, &match_ll, 0);
2815 rsp->status = rte_pipeline_table_entry_delete(p->p,
2824 static struct pipeline_msg_rsp *
2825 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
2826 struct pipeline_msg_req *req)
2828 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2829 uint32_t table_id = req->id;
2831 rsp->status = rte_pipeline_table_default_entry_delete(p->p,
2838 static struct pipeline_msg_rsp *
2839 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
2840 struct pipeline_msg_req *req)
2842 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2843 uint32_t table_id = req->id;
2844 void *data = req->table_rule_stats_read.data;
2845 int clear = req->table_rule_stats_read.clear;
2846 struct rte_table_action *a = p->table_data[table_id].a;
2848 rsp->status = rte_table_action_stats_read(a,
2850 &rsp->table_rule_stats_read.stats,
2856 static struct pipeline_msg_rsp *
2857 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
2858 struct pipeline_msg_req *req)
2860 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2861 uint32_t table_id = req->id;
2862 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
2863 struct rte_table_action_meter_profile *profile =
2864 &req->table_mtr_profile_add.profile;
2865 struct rte_table_action *a = p->table_data[table_id].a;
2867 rsp->status = rte_table_action_meter_profile_add(a,
2874 static struct pipeline_msg_rsp *
2875 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
2876 struct pipeline_msg_req *req)
2878 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2879 uint32_t table_id = req->id;
2880 uint32_t meter_profile_id =
2881 req->table_mtr_profile_delete.meter_profile_id;
2882 struct rte_table_action *a = p->table_data[table_id].a;
2884 rsp->status = rte_table_action_meter_profile_delete(a,
2890 static struct pipeline_msg_rsp *
2891 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
2892 struct pipeline_msg_req *req)
2894 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2895 uint32_t table_id = req->id;
2896 void *data = req->table_rule_mtr_read.data;
2897 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
2898 int clear = req->table_rule_mtr_read.clear;
2899 struct rte_table_action *a = p->table_data[table_id].a;
2901 rsp->status = rte_table_action_meter_read(a,
2904 &rsp->table_rule_mtr_read.stats,
2910 static struct pipeline_msg_rsp *
2911 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
2912 struct pipeline_msg_req *req)
2914 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2915 uint32_t table_id = req->id;
2916 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
2917 struct rte_table_action_dscp_table *dscp_table =
2918 &req->table_dscp_table_update.dscp_table;
2919 struct rte_table_action *a = p->table_data[table_id].a;
2921 rsp->status = rte_table_action_dscp_table_update(a,
2928 static struct pipeline_msg_rsp *
2929 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
2930 struct pipeline_msg_req *req)
2932 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
2933 uint32_t table_id = req->id;
2934 void *data = req->table_rule_ttl_read.data;
2935 int clear = req->table_rule_ttl_read.clear;
2936 struct rte_table_action *a = p->table_data[table_id].a;
2938 rsp->status = rte_table_action_ttl_read(a,
2940 &rsp->table_rule_ttl_read.stats,
2947 pipeline_msg_handle(struct pipeline_data *p)
2950 struct pipeline_msg_req *req;
2951 struct pipeline_msg_rsp *rsp;
2953 req = pipeline_msg_recv(p->msgq_req);
2957 switch (req->type) {
2958 case PIPELINE_REQ_PORT_IN_STATS_READ:
2959 rsp = pipeline_msg_handle_port_in_stats_read(p, req);
2962 case PIPELINE_REQ_PORT_IN_ENABLE:
2963 rsp = pipeline_msg_handle_port_in_enable(p, req);
2966 case PIPELINE_REQ_PORT_IN_DISABLE:
2967 rsp = pipeline_msg_handle_port_in_disable(p, req);
2970 case PIPELINE_REQ_PORT_OUT_STATS_READ:
2971 rsp = pipeline_msg_handle_port_out_stats_read(p, req);
2974 case PIPELINE_REQ_TABLE_STATS_READ:
2975 rsp = pipeline_msg_handle_table_stats_read(p, req);
2978 case PIPELINE_REQ_TABLE_RULE_ADD:
2979 rsp = pipeline_msg_handle_table_rule_add(p, req);
2982 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
2983 rsp = pipeline_msg_handle_table_rule_add_default(p, req);
2986 case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
2987 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
2990 case PIPELINE_REQ_TABLE_RULE_DELETE:
2991 rsp = pipeline_msg_handle_table_rule_delete(p, req);
2994 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
2995 rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
2998 case PIPELINE_REQ_TABLE_RULE_STATS_READ:
2999 rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
3002 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
3003 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
3006 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
3007 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
3010 case PIPELINE_REQ_TABLE_RULE_MTR_READ:
3011 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
3014 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
3015 rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
3018 case PIPELINE_REQ_TABLE_RULE_TTL_READ:
3019 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
3023 rsp = (struct pipeline_msg_rsp *)req;
3027 pipeline_msg_send(p->msgq_rsp, rsp);
3032 * Data plane threads: main
3035 rte_pmd_softnic_run_internal(void *arg)
3037 struct rte_eth_dev *dev = arg;
3038 struct pmd_internals *softnic;
3039 struct softnic_thread_data *t;
3040 uint32_t thread_id, j;
3042 softnic = dev->data->dev_private;
3043 thread_id = rte_lcore_id();
3044 t = &softnic->thread_data[thread_id];
3048 for (j = 0; j < t->n_pipelines; j++)
3049 rte_pipeline_run(t->p[j]);
3052 if ((t->iter & 0xFLLU) == 0) {
3053 uint64_t time = rte_get_tsc_cycles();
3054 uint64_t time_next_min = UINT64_MAX;
3056 if (time < t->time_next_min)
3059 /* Pipeline message queues */
3060 for (j = 0; j < t->n_pipelines; j++) {
3061 struct pipeline_data *p =
3062 &t->pipeline_data[j];
3063 uint64_t time_next = p->time_next;
3065 if (time_next <= time) {
3066 pipeline_msg_handle(p);
3067 rte_pipeline_flush(p->p);
3068 time_next = time + p->timer_period;
3069 p->time_next = time_next;
3072 if (time_next < time_next_min)
3073 time_next_min = time_next;
3076 /* Thread message queues */
3078 uint64_t time_next = t->time_next;
3080 if (time_next <= time) {
3081 thread_msg_handle(t);
3082 time_next = time + t->timer_period;
3083 t->time_next = time_next;
3086 if (time_next < time_next_min)
3087 time_next_min = time_next;
3090 t->time_next_min = time_next_min;
3097 rte_pmd_softnic_run(uint16_t port_id)
3099 struct rte_eth_dev *dev = &rte_eth_devices[port_id];
3101 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
3102 RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
3105 return (int)rte_pmd_softnic_run_internal(dev);