1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
7 #include <rte_common.h>
8 #include <rte_cycles.h>
12 #include <rte_table_acl.h>
13 #include <rte_table_array.h>
14 #include <rte_table_hash.h>
15 #include <rte_table_lpm.h>
16 #include <rte_table_lpm_ipv6.h>
22 #ifndef THREAD_PIPELINES_MAX
23 #define THREAD_PIPELINES_MAX 256
26 #ifndef THREAD_MSGQ_SIZE
27 #define THREAD_MSGQ_SIZE 64
30 #ifndef THREAD_TIMER_PERIOD_MS
31 #define THREAD_TIMER_PERIOD_MS 100
35 * Master thead: data plane thread context
38 struct rte_ring
*msgq_req
;
39 struct rte_ring
*msgq_rsp
;
44 static struct thread thread
[RTE_MAX_LCORE
];
47 * Data plane threads: context
50 struct rte_table_action
*a
;
53 struct pipeline_data
{
54 struct rte_pipeline
*p
;
55 struct table_data table_data
[RTE_PIPELINE_TABLE_MAX
];
58 struct rte_ring
*msgq_req
;
59 struct rte_ring
*msgq_rsp
;
60 uint64_t timer_period
; /* Measured in CPU cycles. */
63 uint8_t buffer
[TABLE_RULE_ACTION_SIZE_MAX
];
67 struct rte_pipeline
*p
[THREAD_PIPELINES_MAX
];
70 struct pipeline_data pipeline_data
[THREAD_PIPELINES_MAX
];
71 struct rte_ring
*msgq_req
;
72 struct rte_ring
*msgq_rsp
;
73 uint64_t timer_period
; /* Measured in CPU cycles. */
75 uint64_t time_next_min
;
76 } __rte_cache_aligned
;
78 static struct thread_data thread_data
[RTE_MAX_LCORE
];
81 * Master thread: data plane thread init
88 for (i
= 0; i
< RTE_MAX_LCORE
; i
++) {
89 struct thread
*t
= &thread
[i
];
91 if (!rte_lcore_is_enabled(i
))
96 rte_ring_free(t
->msgq_req
);
99 rte_ring_free(t
->msgq_rsp
);
108 RTE_LCORE_FOREACH_SLAVE(i
) {
110 struct rte_ring
*msgq_req
, *msgq_rsp
;
111 struct thread
*t
= &thread
[i
];
112 struct thread_data
*t_data
= &thread_data
[i
];
113 uint32_t cpu_id
= rte_lcore_to_socket_id(i
);
116 snprintf(name
, sizeof(name
), "THREAD-%04x-MSGQ-REQ", i
);
118 msgq_req
= rte_ring_create(name
,
121 RING_F_SP_ENQ
| RING_F_SC_DEQ
);
123 if (msgq_req
== NULL
) {
128 snprintf(name
, sizeof(name
), "THREAD-%04x-MSGQ-RSP", i
);
130 msgq_rsp
= rte_ring_create(name
,
133 RING_F_SP_ENQ
| RING_F_SC_DEQ
);
135 if (msgq_rsp
== NULL
) {
140 /* Master thread records */
141 t
->msgq_req
= msgq_req
;
142 t
->msgq_rsp
= msgq_rsp
;
145 /* Data plane thread records */
146 t_data
->n_pipelines
= 0;
147 t_data
->msgq_req
= msgq_req
;
148 t_data
->msgq_rsp
= msgq_rsp
;
149 t_data
->timer_period
=
150 (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS
) / 1000;
151 t_data
->time_next
= rte_get_tsc_cycles() + t_data
->timer_period
;
152 t_data
->time_next_min
= t_data
->time_next
;
159 thread_is_running(uint32_t thread_id
)
161 enum rte_lcore_state_t thread_state
;
163 thread_state
= rte_eal_get_lcore_state(thread_id
);
164 return (thread_state
== RUNNING
) ? 1 : 0;
168 * Pipeline is running when:
169 * (A) Pipeline is mapped to a data plane thread AND
170 * (B) Its data plane thread is in RUNNING state.
173 pipeline_is_running(struct pipeline
*p
)
178 return thread_is_running(p
->thread_id
);
182 * Master thread & data plane threads: message passing
184 enum thread_req_type
{
185 THREAD_REQ_PIPELINE_ENABLE
= 0,
186 THREAD_REQ_PIPELINE_DISABLE
,
190 struct thread_msg_req
{
191 enum thread_req_type type
;
195 struct rte_pipeline
*p
;
197 struct rte_table_action
*a
;
198 } table
[RTE_PIPELINE_TABLE_MAX
];
199 struct rte_ring
*msgq_req
;
200 struct rte_ring
*msgq_rsp
;
201 uint32_t timer_period_ms
;
206 struct rte_pipeline
*p
;
211 struct thread_msg_rsp
{
218 static struct thread_msg_req
*
219 thread_msg_alloc(void)
221 size_t size
= RTE_MAX(sizeof(struct thread_msg_req
),
222 sizeof(struct thread_msg_rsp
));
224 return calloc(1, size
);
228 thread_msg_free(struct thread_msg_rsp
*rsp
)
233 static struct thread_msg_rsp
*
234 thread_msg_send_recv(uint32_t thread_id
,
235 struct thread_msg_req
*req
)
237 struct thread
*t
= &thread
[thread_id
];
238 struct rte_ring
*msgq_req
= t
->msgq_req
;
239 struct rte_ring
*msgq_rsp
= t
->msgq_rsp
;
240 struct thread_msg_rsp
*rsp
;
245 status
= rte_ring_sp_enqueue(msgq_req
, req
);
246 } while (status
== -ENOBUFS
);
250 status
= rte_ring_sc_dequeue(msgq_rsp
, (void **) &rsp
);
251 } while (status
!= 0);
257 thread_pipeline_enable(uint32_t thread_id
,
258 const char *pipeline_name
)
260 struct pipeline
*p
= pipeline_find(pipeline_name
);
262 struct thread_msg_req
*req
;
263 struct thread_msg_rsp
*rsp
;
267 /* Check input params */
268 if ((thread_id
>= RTE_MAX_LCORE
) ||
270 (p
->n_ports_in
== 0) ||
271 (p
->n_ports_out
== 0) ||
275 t
= &thread
[thread_id
];
276 if ((t
->enabled
== 0) ||
280 if (!thread_is_running(thread_id
)) {
281 struct thread_data
*td
= &thread_data
[thread_id
];
282 struct pipeline_data
*tdp
= &td
->pipeline_data
[td
->n_pipelines
];
284 if (td
->n_pipelines
>= THREAD_PIPELINES_MAX
)
287 /* Data plane thread */
288 td
->p
[td
->n_pipelines
] = p
->p
;
291 for (i
= 0; i
< p
->n_tables
; i
++)
292 tdp
->table_data
[i
].a
= p
->table
[i
].a
;
294 tdp
->n_tables
= p
->n_tables
;
296 tdp
->msgq_req
= p
->msgq_req
;
297 tdp
->msgq_rsp
= p
->msgq_rsp
;
298 tdp
->timer_period
= (rte_get_tsc_hz() * p
->timer_period_ms
) / 1000;
299 tdp
->time_next
= rte_get_tsc_cycles() + tdp
->timer_period
;
304 p
->thread_id
= thread_id
;
310 /* Allocate request */
311 req
= thread_msg_alloc();
316 req
->type
= THREAD_REQ_PIPELINE_ENABLE
;
317 req
->pipeline_enable
.p
= p
->p
;
318 for (i
= 0; i
< p
->n_tables
; i
++)
319 req
->pipeline_enable
.table
[i
].a
=
321 req
->pipeline_enable
.msgq_req
= p
->msgq_req
;
322 req
->pipeline_enable
.msgq_rsp
= p
->msgq_rsp
;
323 req
->pipeline_enable
.timer_period_ms
= p
->timer_period_ms
;
324 req
->pipeline_enable
.n_tables
= p
->n_tables
;
326 /* Send request and wait for response */
327 rsp
= thread_msg_send_recv(thread_id
, req
);
332 status
= rsp
->status
;
335 thread_msg_free(rsp
);
337 /* Request completion */
341 p
->thread_id
= thread_id
;
348 thread_pipeline_disable(uint32_t thread_id
,
349 const char *pipeline_name
)
351 struct pipeline
*p
= pipeline_find(pipeline_name
);
353 struct thread_msg_req
*req
;
354 struct thread_msg_rsp
*rsp
;
357 /* Check input params */
358 if ((thread_id
>= RTE_MAX_LCORE
) ||
362 t
= &thread
[thread_id
];
369 if (p
->thread_id
!= thread_id
)
372 if (!thread_is_running(thread_id
)) {
373 struct thread_data
*td
= &thread_data
[thread_id
];
376 for (i
= 0; i
< td
->n_pipelines
; i
++) {
377 struct pipeline_data
*tdp
= &td
->pipeline_data
[i
];
382 /* Data plane thread */
383 if (i
< td
->n_pipelines
- 1) {
384 struct rte_pipeline
*pipeline_last
=
385 td
->p
[td
->n_pipelines
- 1];
386 struct pipeline_data
*tdp_last
=
387 &td
->pipeline_data
[td
->n_pipelines
- 1];
389 td
->p
[i
] = pipeline_last
;
390 memcpy(tdp
, tdp_last
, sizeof(*tdp
));
404 /* Allocate request */
405 req
= thread_msg_alloc();
410 req
->type
= THREAD_REQ_PIPELINE_DISABLE
;
411 req
->pipeline_disable
.p
= p
->p
;
413 /* Send request and wait for response */
414 rsp
= thread_msg_send_recv(thread_id
, req
);
419 status
= rsp
->status
;
422 thread_msg_free(rsp
);
424 /* Request completion */
434 * Data plane threads: message handling
436 static inline struct thread_msg_req
*
437 thread_msg_recv(struct rte_ring
*msgq_req
)
439 struct thread_msg_req
*req
;
441 int status
= rte_ring_sc_dequeue(msgq_req
, (void **) &req
);
450 thread_msg_send(struct rte_ring
*msgq_rsp
,
451 struct thread_msg_rsp
*rsp
)
456 status
= rte_ring_sp_enqueue(msgq_rsp
, rsp
);
457 } while (status
== -ENOBUFS
);
460 static struct thread_msg_rsp
*
461 thread_msg_handle_pipeline_enable(struct thread_data
*t
,
462 struct thread_msg_req
*req
)
464 struct thread_msg_rsp
*rsp
= (struct thread_msg_rsp
*) req
;
465 struct pipeline_data
*p
= &t
->pipeline_data
[t
->n_pipelines
];
469 if (t
->n_pipelines
>= THREAD_PIPELINES_MAX
) {
474 t
->p
[t
->n_pipelines
] = req
->pipeline_enable
.p
;
476 p
->p
= req
->pipeline_enable
.p
;
477 for (i
= 0; i
< req
->pipeline_enable
.n_tables
; i
++)
479 req
->pipeline_enable
.table
[i
].a
;
481 p
->n_tables
= req
->pipeline_enable
.n_tables
;
483 p
->msgq_req
= req
->pipeline_enable
.msgq_req
;
484 p
->msgq_rsp
= req
->pipeline_enable
.msgq_rsp
;
486 (rte_get_tsc_hz() * req
->pipeline_enable
.timer_period_ms
) / 1000;
487 p
->time_next
= rte_get_tsc_cycles() + p
->timer_period
;
496 static struct thread_msg_rsp
*
497 thread_msg_handle_pipeline_disable(struct thread_data
*t
,
498 struct thread_msg_req
*req
)
500 struct thread_msg_rsp
*rsp
= (struct thread_msg_rsp
*) req
;
501 uint32_t n_pipelines
= t
->n_pipelines
;
502 struct rte_pipeline
*pipeline
= req
->pipeline_disable
.p
;
506 for (i
= 0; i
< n_pipelines
; i
++) {
507 struct pipeline_data
*p
= &t
->pipeline_data
[i
];
509 if (p
->p
!= pipeline
)
512 if (i
< n_pipelines
- 1) {
513 struct rte_pipeline
*pipeline_last
=
514 t
->p
[n_pipelines
- 1];
515 struct pipeline_data
*p_last
=
516 &t
->pipeline_data
[n_pipelines
- 1];
518 t
->p
[i
] = pipeline_last
;
519 memcpy(p
, p_last
, sizeof(*p
));
528 /* should not get here */
534 thread_msg_handle(struct thread_data
*t
)
537 struct thread_msg_req
*req
;
538 struct thread_msg_rsp
*rsp
;
540 req
= thread_msg_recv(t
->msgq_req
);
545 case THREAD_REQ_PIPELINE_ENABLE
:
546 rsp
= thread_msg_handle_pipeline_enable(t
, req
);
549 case THREAD_REQ_PIPELINE_DISABLE
:
550 rsp
= thread_msg_handle_pipeline_disable(t
, req
);
554 rsp
= (struct thread_msg_rsp
*) req
;
558 thread_msg_send(t
->msgq_rsp
, rsp
);
563 * Master thread & data plane threads: message passing
565 enum pipeline_req_type
{
567 PIPELINE_REQ_PORT_IN_STATS_READ
,
568 PIPELINE_REQ_PORT_IN_ENABLE
,
569 PIPELINE_REQ_PORT_IN_DISABLE
,
572 PIPELINE_REQ_PORT_OUT_STATS_READ
,
575 PIPELINE_REQ_TABLE_STATS_READ
,
576 PIPELINE_REQ_TABLE_RULE_ADD
,
577 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT
,
578 PIPELINE_REQ_TABLE_RULE_ADD_BULK
,
579 PIPELINE_REQ_TABLE_RULE_DELETE
,
580 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT
,
581 PIPELINE_REQ_TABLE_RULE_STATS_READ
,
582 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD
,
583 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE
,
584 PIPELINE_REQ_TABLE_RULE_MTR_READ
,
585 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE
,
586 PIPELINE_REQ_TABLE_RULE_TTL_READ
,
590 struct pipeline_msg_req_port_in_stats_read
{
594 struct pipeline_msg_req_port_out_stats_read
{
598 struct pipeline_msg_req_table_stats_read
{
602 struct pipeline_msg_req_table_rule_add
{
603 struct table_rule_match match
;
604 struct table_rule_action action
;
607 struct pipeline_msg_req_table_rule_add_default
{
608 struct table_rule_action action
;
611 struct pipeline_msg_req_table_rule_add_bulk
{
612 struct table_rule_match
*match
;
613 struct table_rule_action
*action
;
619 struct pipeline_msg_req_table_rule_delete
{
620 struct table_rule_match match
;
623 struct pipeline_msg_req_table_rule_stats_read
{
628 struct pipeline_msg_req_table_mtr_profile_add
{
629 uint32_t meter_profile_id
;
630 struct rte_table_action_meter_profile profile
;
633 struct pipeline_msg_req_table_mtr_profile_delete
{
634 uint32_t meter_profile_id
;
637 struct pipeline_msg_req_table_rule_mtr_read
{
643 struct pipeline_msg_req_table_dscp_table_update
{
645 struct rte_table_action_dscp_table dscp_table
;
648 struct pipeline_msg_req_table_rule_ttl_read
{
653 struct pipeline_msg_req
{
654 enum pipeline_req_type type
;
655 uint32_t id
; /* Port IN, port OUT or table ID */
659 struct pipeline_msg_req_port_in_stats_read port_in_stats_read
;
660 struct pipeline_msg_req_port_out_stats_read port_out_stats_read
;
661 struct pipeline_msg_req_table_stats_read table_stats_read
;
662 struct pipeline_msg_req_table_rule_add table_rule_add
;
663 struct pipeline_msg_req_table_rule_add_default table_rule_add_default
;
664 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk
;
665 struct pipeline_msg_req_table_rule_delete table_rule_delete
;
666 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read
;
667 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add
;
668 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete
;
669 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read
;
670 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update
;
671 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read
;
675 struct pipeline_msg_rsp_port_in_stats_read
{
676 struct rte_pipeline_port_in_stats stats
;
679 struct pipeline_msg_rsp_port_out_stats_read
{
680 struct rte_pipeline_port_out_stats stats
;
683 struct pipeline_msg_rsp_table_stats_read
{
684 struct rte_pipeline_table_stats stats
;
687 struct pipeline_msg_rsp_table_rule_add
{
691 struct pipeline_msg_rsp_table_rule_add_default
{
695 struct pipeline_msg_rsp_table_rule_add_bulk
{
699 struct pipeline_msg_rsp_table_rule_stats_read
{
700 struct rte_table_action_stats_counters stats
;
703 struct pipeline_msg_rsp_table_rule_mtr_read
{
704 struct rte_table_action_mtr_counters stats
;
707 struct pipeline_msg_rsp_table_rule_ttl_read
{
708 struct rte_table_action_ttl_counters stats
;
711 struct pipeline_msg_rsp
{
716 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read
;
717 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read
;
718 struct pipeline_msg_rsp_table_stats_read table_stats_read
;
719 struct pipeline_msg_rsp_table_rule_add table_rule_add
;
720 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default
;
721 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk
;
722 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read
;
723 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read
;
724 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read
;
731 static struct pipeline_msg_req
*
732 pipeline_msg_alloc(void)
734 size_t size
= RTE_MAX(sizeof(struct pipeline_msg_req
),
735 sizeof(struct pipeline_msg_rsp
));
737 return calloc(1, size
);
741 pipeline_msg_free(struct pipeline_msg_rsp
*rsp
)
746 static struct pipeline_msg_rsp
*
747 pipeline_msg_send_recv(struct pipeline
*p
,
748 struct pipeline_msg_req
*req
)
750 struct rte_ring
*msgq_req
= p
->msgq_req
;
751 struct rte_ring
*msgq_rsp
= p
->msgq_rsp
;
752 struct pipeline_msg_rsp
*rsp
;
757 status
= rte_ring_sp_enqueue(msgq_req
, req
);
758 } while (status
== -ENOBUFS
);
762 status
= rte_ring_sc_dequeue(msgq_rsp
, (void **) &rsp
);
763 } while (status
!= 0);
769 pipeline_port_in_stats_read(const char *pipeline_name
,
771 struct rte_pipeline_port_in_stats
*stats
,
775 struct pipeline_msg_req
*req
;
776 struct pipeline_msg_rsp
*rsp
;
779 /* Check input params */
780 if ((pipeline_name
== NULL
) ||
784 p
= pipeline_find(pipeline_name
);
786 (port_id
>= p
->n_ports_in
))
789 if (!pipeline_is_running(p
)) {
790 status
= rte_pipeline_port_in_stats_read(p
->p
,
798 /* Allocate request */
799 req
= pipeline_msg_alloc();
804 req
->type
= PIPELINE_REQ_PORT_IN_STATS_READ
;
806 req
->port_in_stats_read
.clear
= clear
;
808 /* Send request and wait for response */
809 rsp
= pipeline_msg_send_recv(p
, req
);
814 status
= rsp
->status
;
816 memcpy(stats
, &rsp
->port_in_stats_read
.stats
, sizeof(*stats
));
819 pipeline_msg_free(rsp
);
825 pipeline_port_in_enable(const char *pipeline_name
,
829 struct pipeline_msg_req
*req
;
830 struct pipeline_msg_rsp
*rsp
;
833 /* Check input params */
834 if (pipeline_name
== NULL
)
837 p
= pipeline_find(pipeline_name
);
839 (port_id
>= p
->n_ports_in
))
842 if (!pipeline_is_running(p
)) {
843 status
= rte_pipeline_port_in_enable(p
->p
, port_id
);
847 /* Allocate request */
848 req
= pipeline_msg_alloc();
853 req
->type
= PIPELINE_REQ_PORT_IN_ENABLE
;
856 /* Send request and wait for response */
857 rsp
= pipeline_msg_send_recv(p
, req
);
862 status
= rsp
->status
;
865 pipeline_msg_free(rsp
);
871 pipeline_port_in_disable(const char *pipeline_name
,
875 struct pipeline_msg_req
*req
;
876 struct pipeline_msg_rsp
*rsp
;
879 /* Check input params */
880 if (pipeline_name
== NULL
)
883 p
= pipeline_find(pipeline_name
);
885 (port_id
>= p
->n_ports_in
))
888 if (!pipeline_is_running(p
)) {
889 status
= rte_pipeline_port_in_disable(p
->p
, port_id
);
893 /* Allocate request */
894 req
= pipeline_msg_alloc();
899 req
->type
= PIPELINE_REQ_PORT_IN_DISABLE
;
902 /* Send request and wait for response */
903 rsp
= pipeline_msg_send_recv(p
, req
);
908 status
= rsp
->status
;
911 pipeline_msg_free(rsp
);
917 pipeline_port_out_stats_read(const char *pipeline_name
,
919 struct rte_pipeline_port_out_stats
*stats
,
923 struct pipeline_msg_req
*req
;
924 struct pipeline_msg_rsp
*rsp
;
927 /* Check input params */
928 if ((pipeline_name
== NULL
) ||
932 p
= pipeline_find(pipeline_name
);
934 (port_id
>= p
->n_ports_out
))
937 if (!pipeline_is_running(p
)) {
938 status
= rte_pipeline_port_out_stats_read(p
->p
,
946 /* Allocate request */
947 req
= pipeline_msg_alloc();
952 req
->type
= PIPELINE_REQ_PORT_OUT_STATS_READ
;
954 req
->port_out_stats_read
.clear
= clear
;
956 /* Send request and wait for response */
957 rsp
= pipeline_msg_send_recv(p
, req
);
962 status
= rsp
->status
;
964 memcpy(stats
, &rsp
->port_out_stats_read
.stats
, sizeof(*stats
));
967 pipeline_msg_free(rsp
);
973 pipeline_table_stats_read(const char *pipeline_name
,
975 struct rte_pipeline_table_stats
*stats
,
979 struct pipeline_msg_req
*req
;
980 struct pipeline_msg_rsp
*rsp
;
983 /* Check input params */
984 if ((pipeline_name
== NULL
) ||
988 p
= pipeline_find(pipeline_name
);
990 (table_id
>= p
->n_tables
))
993 if (!pipeline_is_running(p
)) {
994 status
= rte_pipeline_table_stats_read(p
->p
,
1002 /* Allocate request */
1003 req
= pipeline_msg_alloc();
1008 req
->type
= PIPELINE_REQ_TABLE_STATS_READ
;
1010 req
->table_stats_read
.clear
= clear
;
1012 /* Send request and wait for response */
1013 rsp
= pipeline_msg_send_recv(p
, req
);
1018 status
= rsp
->status
;
1020 memcpy(stats
, &rsp
->table_stats_read
.stats
, sizeof(*stats
));
1023 pipeline_msg_free(rsp
);
1029 match_check(struct table_rule_match
*match
,
1033 struct table
*table
;
1035 if ((match
== NULL
) ||
1037 (table_id
>= p
->n_tables
))
1040 table
= &p
->table
[table_id
];
1041 if (match
->match_type
!= table
->params
.match_type
)
1044 switch (match
->match_type
) {
1047 struct table_acl_params
*t
= &table
->params
.match
.acl
;
1048 struct table_rule_match_acl
*r
= &match
->match
.acl
;
1050 if ((r
->ip_version
&& (t
->ip_version
== 0)) ||
1051 ((r
->ip_version
== 0) && t
->ip_version
))
1054 if (r
->ip_version
) {
1055 if ((r
->sa_depth
> 32) ||
1059 if ((r
->sa_depth
> 128) ||
1060 (r
->da_depth
> 128))
1074 struct table_lpm_params
*t
= &table
->params
.match
.lpm
;
1075 struct table_rule_match_lpm
*r
= &match
->match
.lpm
;
1077 if ((r
->ip_version
&& (t
->key_size
!= 4)) ||
1078 ((r
->ip_version
== 0) && (t
->key_size
!= 16)))
1081 if (r
->ip_version
) {
1100 action_check(struct table_rule_action
*action
,
1104 struct table_action_profile
*ap
;
1106 if ((action
== NULL
) ||
1108 (table_id
>= p
->n_tables
))
1111 ap
= p
->table
[table_id
].ap
;
1112 if (action
->action_mask
!= ap
->params
.action_mask
)
1115 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_FWD
)) {
1116 if ((action
->fwd
.action
== RTE_PIPELINE_ACTION_PORT
) &&
1117 (action
->fwd
.id
>= p
->n_ports_out
))
1120 if ((action
->fwd
.action
== RTE_PIPELINE_ACTION_TABLE
) &&
1121 (action
->fwd
.id
>= p
->n_tables
))
1125 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_MTR
)) {
1126 uint32_t tc_mask0
= (1 << ap
->params
.mtr
.n_tc
) - 1;
1127 uint32_t tc_mask1
= action
->mtr
.tc_mask
;
1129 if (tc_mask1
!= tc_mask0
)
1133 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_TM
)) {
1134 uint32_t n_subports_per_port
=
1135 ap
->params
.tm
.n_subports_per_port
;
1136 uint32_t n_pipes_per_subport
=
1137 ap
->params
.tm
.n_pipes_per_subport
;
1138 uint32_t subport_id
= action
->tm
.subport_id
;
1139 uint32_t pipe_id
= action
->tm
.pipe_id
;
1141 if ((subport_id
>= n_subports_per_port
) ||
1142 (pipe_id
>= n_pipes_per_subport
))
1146 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_ENCAP
)) {
1147 uint64_t encap_mask
= ap
->params
.encap
.encap_mask
;
1148 enum rte_table_action_encap_type type
= action
->encap
.type
;
1150 if ((encap_mask
& (1LLU << type
)) == 0)
1154 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_NAT
)) {
1155 int ip_version0
= ap
->params
.common
.ip_version
;
1156 int ip_version1
= action
->nat
.ip_version
;
1158 if ((ip_version1
&& (ip_version0
== 0)) ||
1159 ((ip_version1
== 0) && ip_version0
))
1167 action_default_check(struct table_rule_action
*action
,
1171 if ((action
== NULL
) ||
1172 (action
->action_mask
!= (1LLU << RTE_TABLE_ACTION_FWD
)) ||
1174 (table_id
>= p
->n_tables
))
1177 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_FWD
)) {
1178 if ((action
->fwd
.action
== RTE_PIPELINE_ACTION_PORT
) &&
1179 (action
->fwd
.id
>= p
->n_ports_out
))
1182 if ((action
->fwd
.action
== RTE_PIPELINE_ACTION_TABLE
) &&
1183 (action
->fwd
.id
>= p
->n_tables
))
1190 union table_rule_match_low_level
{
1191 struct rte_table_acl_rule_add_params acl_add
;
1192 struct rte_table_acl_rule_delete_params acl_delete
;
1193 struct rte_table_array_key array
;
1194 uint8_t hash
[TABLE_RULE_MATCH_SIZE_MAX
];
1195 struct rte_table_lpm_key lpm_ipv4
;
1196 struct rte_table_lpm_ipv6_key lpm_ipv6
;
1200 match_convert(struct table_rule_match
*mh
,
1201 union table_rule_match_low_level
*ml
,
1205 action_convert(struct rte_table_action
*a
,
1206 struct table_rule_action
*action
,
1207 struct rte_pipeline_table_entry
*data
);
1210 pipeline_table_rule_add(const char *pipeline_name
,
1212 struct table_rule_match
*match
,
1213 struct table_rule_action
*action
,
1217 struct pipeline_msg_req
*req
;
1218 struct pipeline_msg_rsp
*rsp
;
1221 /* Check input params */
1222 if ((pipeline_name
== NULL
) ||
1228 p
= pipeline_find(pipeline_name
);
1230 (table_id
>= p
->n_tables
) ||
1231 match_check(match
, p
, table_id
) ||
1232 action_check(action
, p
, table_id
))
1235 if (!pipeline_is_running(p
)) {
1236 struct rte_table_action
*a
= p
->table
[table_id
].a
;
1237 union table_rule_match_low_level match_ll
;
1238 struct rte_pipeline_table_entry
*data_in
, *data_out
;
1242 buffer
= calloc(TABLE_RULE_ACTION_SIZE_MAX
, sizeof(uint8_t));
1246 /* Table match-action rule conversion */
1247 data_in
= (struct rte_pipeline_table_entry
*)buffer
;
1249 status
= match_convert(match
, &match_ll
, 1);
1255 status
= action_convert(a
, action
, data_in
);
1261 /* Add rule (match, action) to table */
1262 status
= rte_pipeline_table_entry_add(p
->p
,
1273 /* Write Response */
1280 /* Allocate request */
1281 req
= pipeline_msg_alloc();
1286 req
->type
= PIPELINE_REQ_TABLE_RULE_ADD
;
1288 memcpy(&req
->table_rule_add
.match
, match
, sizeof(*match
));
1289 memcpy(&req
->table_rule_add
.action
, action
, sizeof(*action
));
1291 /* Send request and wait for response */
1292 rsp
= pipeline_msg_send_recv(p
, req
);
1297 status
= rsp
->status
;
1299 *data
= rsp
->table_rule_add
.data
;
1302 pipeline_msg_free(rsp
);
1308 pipeline_table_rule_add_default(const char *pipeline_name
,
1310 struct table_rule_action
*action
,
1314 struct pipeline_msg_req
*req
;
1315 struct pipeline_msg_rsp
*rsp
;
1318 /* Check input params */
1319 if ((pipeline_name
== NULL
) ||
1324 p
= pipeline_find(pipeline_name
);
1326 (table_id
>= p
->n_tables
) ||
1327 action_default_check(action
, p
, table_id
))
1330 if (!pipeline_is_running(p
)) {
1331 struct rte_pipeline_table_entry
*data_in
, *data_out
;
1334 buffer
= calloc(TABLE_RULE_ACTION_SIZE_MAX
, sizeof(uint8_t));
1339 data_in
= (struct rte_pipeline_table_entry
*)buffer
;
1341 data_in
->action
= action
->fwd
.action
;
1342 if (action
->fwd
.action
== RTE_PIPELINE_ACTION_PORT
)
1343 data_in
->port_id
= action
->fwd
.id
;
1344 if (action
->fwd
.action
== RTE_PIPELINE_ACTION_TABLE
)
1345 data_in
->table_id
= action
->fwd
.id
;
1347 /* Add default rule to table */
1348 status
= rte_pipeline_table_default_entry_add(p
->p
,
1357 /* Write Response */
1364 /* Allocate request */
1365 req
= pipeline_msg_alloc();
1370 req
->type
= PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT
;
1372 memcpy(&req
->table_rule_add_default
.action
, action
, sizeof(*action
));
1374 /* Send request and wait for response */
1375 rsp
= pipeline_msg_send_recv(p
, req
);
1380 status
= rsp
->status
;
1382 *data
= rsp
->table_rule_add_default
.data
;
1385 pipeline_msg_free(rsp
);
1391 pipeline_table_rule_add_bulk(const char *pipeline_name
,
1393 struct table_rule_match
*match
,
1394 struct table_rule_action
*action
,
1399 struct pipeline_msg_req
*req
;
1400 struct pipeline_msg_rsp
*rsp
;
1404 /* Check input params */
1405 if ((pipeline_name
== NULL
) ||
1409 (n_rules
== NULL
) ||
1413 p
= pipeline_find(pipeline_name
);
1415 (table_id
>= p
->n_tables
))
1418 for (i
= 0; i
< *n_rules
; i
++)
1419 if (match_check(match
, p
, table_id
) ||
1420 action_check(action
, p
, table_id
))
1423 if (!pipeline_is_running(p
)) {
1424 struct rte_table_action
*a
= p
->table
[table_id
].a
;
1425 union table_rule_match_low_level
*match_ll
;
1427 void **match_ll_ptr
;
1428 struct rte_pipeline_table_entry
**action_ll_ptr
;
1429 struct rte_pipeline_table_entry
**entries_ptr
=
1430 (struct rte_pipeline_table_entry
**)data
;
1432 (p
->table
[table_id
].params
.match_type
== TABLE_ACL
) ? 1 : 0;
1435 /* Memory allocation */
1436 match_ll
= calloc(*n_rules
, sizeof(union table_rule_match_low_level
));
1437 action_ll
= calloc(*n_rules
, TABLE_RULE_ACTION_SIZE_MAX
);
1438 match_ll_ptr
= calloc(*n_rules
, sizeof(void *));
1440 calloc(*n_rules
, sizeof(struct rte_pipeline_table_entry
*));
1441 found
= calloc(*n_rules
, sizeof(int));
1443 if (match_ll
== NULL
||
1444 action_ll
== NULL
||
1445 match_ll_ptr
== NULL
||
1446 action_ll_ptr
== NULL
||
1450 for (i
= 0; i
< *n_rules
; i
++) {
1451 match_ll_ptr
[i
] = (void *)&match_ll
[i
];
1453 (struct rte_pipeline_table_entry
*)&action_ll
[i
* TABLE_RULE_ACTION_SIZE_MAX
];
1456 /* Rule match conversion */
1457 for (i
= 0; i
< *n_rules
; i
++) {
1458 status
= match_convert(&match
[i
], match_ll_ptr
[i
], 1);
1463 /* Rule action conversion */
1464 for (i
= 0; i
< *n_rules
; i
++) {
1465 status
= action_convert(a
, &action
[i
], action_ll_ptr
[i
]);
1470 /* Add rule (match, action) to table */
1472 status
= rte_pipeline_table_entry_add_bulk(p
->p
,
1482 for (i
= 0; i
< *n_rules
; i
++) {
1483 status
= rte_pipeline_table_entry_add(p
->p
,
1498 free(action_ll_ptr
);
1507 free(action_ll_ptr
);
1516 /* Allocate request */
1517 req
= pipeline_msg_alloc();
1522 req
->type
= PIPELINE_REQ_TABLE_RULE_ADD_BULK
;
1524 req
->table_rule_add_bulk
.match
= match
;
1525 req
->table_rule_add_bulk
.action
= action
;
1526 req
->table_rule_add_bulk
.data
= data
;
1527 req
->table_rule_add_bulk
.n_rules
= *n_rules
;
1528 req
->table_rule_add_bulk
.bulk
=
1529 (p
->table
[table_id
].params
.match_type
== TABLE_ACL
) ? 1 : 0;
1531 /* Send request and wait for response */
1532 rsp
= pipeline_msg_send_recv(p
, req
);
1537 status
= rsp
->status
;
1539 *n_rules
= rsp
->table_rule_add_bulk
.n_rules
;
1542 pipeline_msg_free(rsp
);
1548 pipeline_table_rule_delete(const char *pipeline_name
,
1550 struct table_rule_match
*match
)
1553 struct pipeline_msg_req
*req
;
1554 struct pipeline_msg_rsp
*rsp
;
1557 /* Check input params */
1558 if ((pipeline_name
== NULL
) ||
1562 p
= pipeline_find(pipeline_name
);
1564 (table_id
>= p
->n_tables
) ||
1565 match_check(match
, p
, table_id
))
1568 if (!pipeline_is_running(p
)) {
1569 union table_rule_match_low_level match_ll
;
1572 status
= match_convert(match
, &match_ll
, 0);
1576 status
= rte_pipeline_table_entry_delete(p
->p
,
1585 /* Allocate request */
1586 req
= pipeline_msg_alloc();
1591 req
->type
= PIPELINE_REQ_TABLE_RULE_DELETE
;
1593 memcpy(&req
->table_rule_delete
.match
, match
, sizeof(*match
));
1595 /* Send request and wait for response */
1596 rsp
= pipeline_msg_send_recv(p
, req
);
1601 status
= rsp
->status
;
1604 pipeline_msg_free(rsp
);
1610 pipeline_table_rule_delete_default(const char *pipeline_name
,
1614 struct pipeline_msg_req
*req
;
1615 struct pipeline_msg_rsp
*rsp
;
1618 /* Check input params */
1619 if (pipeline_name
== NULL
)
1622 p
= pipeline_find(pipeline_name
);
1624 (table_id
>= p
->n_tables
))
1627 if (!pipeline_is_running(p
)) {
1628 status
= rte_pipeline_table_default_entry_delete(p
->p
,
1635 /* Allocate request */
1636 req
= pipeline_msg_alloc();
1641 req
->type
= PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT
;
1644 /* Send request and wait for response */
1645 rsp
= pipeline_msg_send_recv(p
, req
);
1650 status
= rsp
->status
;
1653 pipeline_msg_free(rsp
);
1659 pipeline_table_rule_stats_read(const char *pipeline_name
,
1662 struct rte_table_action_stats_counters
*stats
,
1666 struct pipeline_msg_req
*req
;
1667 struct pipeline_msg_rsp
*rsp
;
1670 /* Check input params */
1671 if ((pipeline_name
== NULL
) ||
1676 p
= pipeline_find(pipeline_name
);
1678 (table_id
>= p
->n_tables
))
1681 if (!pipeline_is_running(p
)) {
1682 struct rte_table_action
*a
= p
->table
[table_id
].a
;
1684 status
= rte_table_action_stats_read(a
,
1692 /* Allocate request */
1693 req
= pipeline_msg_alloc();
1698 req
->type
= PIPELINE_REQ_TABLE_RULE_STATS_READ
;
1700 req
->table_rule_stats_read
.data
= data
;
1701 req
->table_rule_stats_read
.clear
= clear
;
1703 /* Send request and wait for response */
1704 rsp
= pipeline_msg_send_recv(p
, req
);
1709 status
= rsp
->status
;
1711 memcpy(stats
, &rsp
->table_rule_stats_read
.stats
, sizeof(*stats
));
1714 pipeline_msg_free(rsp
);
1720 pipeline_table_mtr_profile_add(const char *pipeline_name
,
1722 uint32_t meter_profile_id
,
1723 struct rte_table_action_meter_profile
*profile
)
1726 struct pipeline_msg_req
*req
;
1727 struct pipeline_msg_rsp
*rsp
;
1730 /* Check input params */
1731 if ((pipeline_name
== NULL
) ||
1735 p
= pipeline_find(pipeline_name
);
1737 (table_id
>= p
->n_tables
))
1740 if (!pipeline_is_running(p
)) {
1741 struct rte_table_action
*a
= p
->table
[table_id
].a
;
1743 status
= rte_table_action_meter_profile_add(a
,
1750 /* Allocate request */
1751 req
= pipeline_msg_alloc();
1756 req
->type
= PIPELINE_REQ_TABLE_MTR_PROFILE_ADD
;
1758 req
->table_mtr_profile_add
.meter_profile_id
= meter_profile_id
;
1759 memcpy(&req
->table_mtr_profile_add
.profile
, profile
, sizeof(*profile
));
1761 /* Send request and wait for response */
1762 rsp
= pipeline_msg_send_recv(p
, req
);
1767 status
= rsp
->status
;
1770 pipeline_msg_free(rsp
);
1776 pipeline_table_mtr_profile_delete(const char *pipeline_name
,
1778 uint32_t meter_profile_id
)
1781 struct pipeline_msg_req
*req
;
1782 struct pipeline_msg_rsp
*rsp
;
1785 /* Check input params */
1786 if (pipeline_name
== NULL
)
1789 p
= pipeline_find(pipeline_name
);
1791 (table_id
>= p
->n_tables
))
1794 if (!pipeline_is_running(p
)) {
1795 struct rte_table_action
*a
= p
->table
[table_id
].a
;
1797 status
= rte_table_action_meter_profile_delete(a
,
1803 /* Allocate request */
1804 req
= pipeline_msg_alloc();
1809 req
->type
= PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE
;
1811 req
->table_mtr_profile_delete
.meter_profile_id
= meter_profile_id
;
1813 /* Send request and wait for response */
1814 rsp
= pipeline_msg_send_recv(p
, req
);
1819 status
= rsp
->status
;
1822 pipeline_msg_free(rsp
);
1828 pipeline_table_rule_mtr_read(const char *pipeline_name
,
1832 struct rte_table_action_mtr_counters
*stats
,
1836 struct pipeline_msg_req
*req
;
1837 struct pipeline_msg_rsp
*rsp
;
1840 /* Check input params */
1841 if ((pipeline_name
== NULL
) ||
1846 p
= pipeline_find(pipeline_name
);
1848 (table_id
>= p
->n_tables
))
1851 if (!pipeline_is_running(p
)) {
1852 struct rte_table_action
*a
= p
->table
[table_id
].a
;
1854 status
= rte_table_action_meter_read(a
,
1863 /* Allocate request */
1864 req
= pipeline_msg_alloc();
1869 req
->type
= PIPELINE_REQ_TABLE_RULE_MTR_READ
;
1871 req
->table_rule_mtr_read
.data
= data
;
1872 req
->table_rule_mtr_read
.tc_mask
= tc_mask
;
1873 req
->table_rule_mtr_read
.clear
= clear
;
1875 /* Send request and wait for response */
1876 rsp
= pipeline_msg_send_recv(p
, req
);
1881 status
= rsp
->status
;
1883 memcpy(stats
, &rsp
->table_rule_mtr_read
.stats
, sizeof(*stats
));
1886 pipeline_msg_free(rsp
);
1892 pipeline_table_dscp_table_update(const char *pipeline_name
,
1895 struct rte_table_action_dscp_table
*dscp_table
)
1898 struct pipeline_msg_req
*req
;
1899 struct pipeline_msg_rsp
*rsp
;
1902 /* Check input params */
1903 if ((pipeline_name
== NULL
) ||
1904 (dscp_table
== NULL
))
1907 p
= pipeline_find(pipeline_name
);
1909 (table_id
>= p
->n_tables
))
1912 if (!pipeline_is_running(p
)) {
1913 struct rte_table_action
*a
= p
->table
[table_id
].a
;
1915 status
= rte_table_action_dscp_table_update(a
,
1922 /* Allocate request */
1923 req
= pipeline_msg_alloc();
1928 req
->type
= PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE
;
1930 req
->table_dscp_table_update
.dscp_mask
= dscp_mask
;
1931 memcpy(&req
->table_dscp_table_update
.dscp_table
,
1932 dscp_table
, sizeof(*dscp_table
));
1934 /* Send request and wait for response */
1935 rsp
= pipeline_msg_send_recv(p
, req
);
1940 status
= rsp
->status
;
1943 pipeline_msg_free(rsp
);
1949 pipeline_table_rule_ttl_read(const char *pipeline_name
,
1952 struct rte_table_action_ttl_counters
*stats
,
1956 struct pipeline_msg_req
*req
;
1957 struct pipeline_msg_rsp
*rsp
;
1960 /* Check input params */
1961 if ((pipeline_name
== NULL
) ||
1966 p
= pipeline_find(pipeline_name
);
1968 (table_id
>= p
->n_tables
))
1971 if (!pipeline_is_running(p
)) {
1972 struct rte_table_action
*a
= p
->table
[table_id
].a
;
1974 status
= rte_table_action_ttl_read(a
,
1982 /* Allocate request */
1983 req
= pipeline_msg_alloc();
1988 req
->type
= PIPELINE_REQ_TABLE_RULE_TTL_READ
;
1990 req
->table_rule_ttl_read
.data
= data
;
1991 req
->table_rule_ttl_read
.clear
= clear
;
1993 /* Send request and wait for response */
1994 rsp
= pipeline_msg_send_recv(p
, req
);
1999 status
= rsp
->status
;
2001 memcpy(stats
, &rsp
->table_rule_ttl_read
.stats
, sizeof(*stats
));
2004 pipeline_msg_free(rsp
);
2010 * Data plane threads: message handling
2012 static inline struct pipeline_msg_req
*
2013 pipeline_msg_recv(struct rte_ring
*msgq_req
)
2015 struct pipeline_msg_req
*req
;
2017 int status
= rte_ring_sc_dequeue(msgq_req
, (void **) &req
);
2026 pipeline_msg_send(struct rte_ring
*msgq_rsp
,
2027 struct pipeline_msg_rsp
*rsp
)
2032 status
= rte_ring_sp_enqueue(msgq_rsp
, rsp
);
2033 } while (status
== -ENOBUFS
);
2036 static struct pipeline_msg_rsp
*
2037 pipeline_msg_handle_port_in_stats_read(struct pipeline_data
*p
,
2038 struct pipeline_msg_req
*req
)
2040 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2041 uint32_t port_id
= req
->id
;
2042 int clear
= req
->port_in_stats_read
.clear
;
2044 rsp
->status
= rte_pipeline_port_in_stats_read(p
->p
,
2046 &rsp
->port_in_stats_read
.stats
,
2052 static struct pipeline_msg_rsp
*
2053 pipeline_msg_handle_port_in_enable(struct pipeline_data
*p
,
2054 struct pipeline_msg_req
*req
)
2056 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2057 uint32_t port_id
= req
->id
;
2059 rsp
->status
= rte_pipeline_port_in_enable(p
->p
,
2065 static struct pipeline_msg_rsp
*
2066 pipeline_msg_handle_port_in_disable(struct pipeline_data
*p
,
2067 struct pipeline_msg_req
*req
)
2069 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2070 uint32_t port_id
= req
->id
;
2072 rsp
->status
= rte_pipeline_port_in_disable(p
->p
,
2078 static struct pipeline_msg_rsp
*
2079 pipeline_msg_handle_port_out_stats_read(struct pipeline_data
*p
,
2080 struct pipeline_msg_req
*req
)
2082 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2083 uint32_t port_id
= req
->id
;
2084 int clear
= req
->port_out_stats_read
.clear
;
2086 rsp
->status
= rte_pipeline_port_out_stats_read(p
->p
,
2088 &rsp
->port_out_stats_read
.stats
,
2094 static struct pipeline_msg_rsp
*
2095 pipeline_msg_handle_table_stats_read(struct pipeline_data
*p
,
2096 struct pipeline_msg_req
*req
)
2098 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2099 uint32_t port_id
= req
->id
;
2100 int clear
= req
->table_stats_read
.clear
;
2102 rsp
->status
= rte_pipeline_table_stats_read(p
->p
,
2104 &rsp
->table_stats_read
.stats
,
2111 match_convert_ipv6_depth(uint32_t depth
, uint32_t *depth32
)
2116 switch (depth
/ 32) {
2126 depth32
[1] = depth
- 32;
2134 depth32
[2] = depth
- 64;
2142 depth32
[3] = depth
- 96;
2158 match_convert(struct table_rule_match
*mh
,
2159 union table_rule_match_low_level
*ml
,
2162 memset(ml
, 0, sizeof(*ml
));
2164 switch (mh
->match_type
) {
2166 if (mh
->match
.acl
.ip_version
)
2168 ml
->acl_add
.field_value
[0].value
.u8
=
2169 mh
->match
.acl
.proto
;
2170 ml
->acl_add
.field_value
[0].mask_range
.u8
=
2171 mh
->match
.acl
.proto_mask
;
2173 ml
->acl_add
.field_value
[1].value
.u32
=
2174 mh
->match
.acl
.ipv4
.sa
;
2175 ml
->acl_add
.field_value
[1].mask_range
.u32
=
2176 mh
->match
.acl
.sa_depth
;
2178 ml
->acl_add
.field_value
[2].value
.u32
=
2179 mh
->match
.acl
.ipv4
.da
;
2180 ml
->acl_add
.field_value
[2].mask_range
.u32
=
2181 mh
->match
.acl
.da_depth
;
2183 ml
->acl_add
.field_value
[3].value
.u16
=
2185 ml
->acl_add
.field_value
[3].mask_range
.u16
=
2188 ml
->acl_add
.field_value
[4].value
.u16
=
2190 ml
->acl_add
.field_value
[4].mask_range
.u16
=
2193 ml
->acl_add
.priority
=
2194 (int32_t) mh
->match
.acl
.priority
;
2196 ml
->acl_delete
.field_value
[0].value
.u8
=
2197 mh
->match
.acl
.proto
;
2198 ml
->acl_delete
.field_value
[0].mask_range
.u8
=
2199 mh
->match
.acl
.proto_mask
;
2201 ml
->acl_delete
.field_value
[1].value
.u32
=
2202 mh
->match
.acl
.ipv4
.sa
;
2203 ml
->acl_delete
.field_value
[1].mask_range
.u32
=
2204 mh
->match
.acl
.sa_depth
;
2206 ml
->acl_delete
.field_value
[2].value
.u32
=
2207 mh
->match
.acl
.ipv4
.da
;
2208 ml
->acl_delete
.field_value
[2].mask_range
.u32
=
2209 mh
->match
.acl
.da_depth
;
2211 ml
->acl_delete
.field_value
[3].value
.u16
=
2213 ml
->acl_delete
.field_value
[3].mask_range
.u16
=
2216 ml
->acl_delete
.field_value
[4].value
.u16
=
2218 ml
->acl_delete
.field_value
[4].mask_range
.u16
=
2224 (uint32_t *) mh
->match
.acl
.ipv6
.sa
;
2226 (uint32_t *) mh
->match
.acl
.ipv6
.da
;
2227 uint32_t sa32_depth
[4], da32_depth
[4];
2230 status
= match_convert_ipv6_depth(
2231 mh
->match
.acl
.sa_depth
,
2236 status
= match_convert_ipv6_depth(
2237 mh
->match
.acl
.da_depth
,
2242 ml
->acl_add
.field_value
[0].value
.u8
=
2243 mh
->match
.acl
.proto
;
2244 ml
->acl_add
.field_value
[0].mask_range
.u8
=
2245 mh
->match
.acl
.proto_mask
;
2247 ml
->acl_add
.field_value
[1].value
.u32
= sa32
[0];
2248 ml
->acl_add
.field_value
[1].mask_range
.u32
=
2250 ml
->acl_add
.field_value
[2].value
.u32
= sa32
[1];
2251 ml
->acl_add
.field_value
[2].mask_range
.u32
=
2253 ml
->acl_add
.field_value
[3].value
.u32
= sa32
[2];
2254 ml
->acl_add
.field_value
[3].mask_range
.u32
=
2256 ml
->acl_add
.field_value
[4].value
.u32
= sa32
[3];
2257 ml
->acl_add
.field_value
[4].mask_range
.u32
=
2260 ml
->acl_add
.field_value
[5].value
.u32
= da32
[0];
2261 ml
->acl_add
.field_value
[5].mask_range
.u32
=
2263 ml
->acl_add
.field_value
[6].value
.u32
= da32
[1];
2264 ml
->acl_add
.field_value
[6].mask_range
.u32
=
2266 ml
->acl_add
.field_value
[7].value
.u32
= da32
[2];
2267 ml
->acl_add
.field_value
[7].mask_range
.u32
=
2269 ml
->acl_add
.field_value
[8].value
.u32
= da32
[3];
2270 ml
->acl_add
.field_value
[8].mask_range
.u32
=
2273 ml
->acl_add
.field_value
[9].value
.u16
=
2275 ml
->acl_add
.field_value
[9].mask_range
.u16
=
2278 ml
->acl_add
.field_value
[10].value
.u16
=
2280 ml
->acl_add
.field_value
[10].mask_range
.u16
=
2283 ml
->acl_add
.priority
=
2284 (int32_t) mh
->match
.acl
.priority
;
2287 (uint32_t *) mh
->match
.acl
.ipv6
.sa
;
2289 (uint32_t *) mh
->match
.acl
.ipv6
.da
;
2290 uint32_t sa32_depth
[4], da32_depth
[4];
2293 status
= match_convert_ipv6_depth(
2294 mh
->match
.acl
.sa_depth
,
2299 status
= match_convert_ipv6_depth(
2300 mh
->match
.acl
.da_depth
,
2305 ml
->acl_delete
.field_value
[0].value
.u8
=
2306 mh
->match
.acl
.proto
;
2307 ml
->acl_delete
.field_value
[0].mask_range
.u8
=
2308 mh
->match
.acl
.proto_mask
;
2310 ml
->acl_delete
.field_value
[1].value
.u32
=
2312 ml
->acl_delete
.field_value
[1].mask_range
.u32
=
2314 ml
->acl_delete
.field_value
[2].value
.u32
=
2316 ml
->acl_delete
.field_value
[2].mask_range
.u32
=
2318 ml
->acl_delete
.field_value
[3].value
.u32
=
2320 ml
->acl_delete
.field_value
[3].mask_range
.u32
=
2322 ml
->acl_delete
.field_value
[4].value
.u32
=
2324 ml
->acl_delete
.field_value
[4].mask_range
.u32
=
2327 ml
->acl_delete
.field_value
[5].value
.u32
=
2329 ml
->acl_delete
.field_value
[5].mask_range
.u32
=
2331 ml
->acl_delete
.field_value
[6].value
.u32
=
2333 ml
->acl_delete
.field_value
[6].mask_range
.u32
=
2335 ml
->acl_delete
.field_value
[7].value
.u32
=
2337 ml
->acl_delete
.field_value
[7].mask_range
.u32
=
2339 ml
->acl_delete
.field_value
[8].value
.u32
=
2341 ml
->acl_delete
.field_value
[8].mask_range
.u32
=
2344 ml
->acl_delete
.field_value
[9].value
.u16
=
2346 ml
->acl_delete
.field_value
[9].mask_range
.u16
=
2349 ml
->acl_delete
.field_value
[10].value
.u16
=
2351 ml
->acl_delete
.field_value
[10].mask_range
.u16
=
2357 ml
->array
.pos
= mh
->match
.array
.pos
;
2361 memcpy(ml
->hash
, mh
->match
.hash
.key
, sizeof(ml
->hash
));
2365 if (mh
->match
.lpm
.ip_version
) {
2366 ml
->lpm_ipv4
.ip
= mh
->match
.lpm
.ipv4
;
2367 ml
->lpm_ipv4
.depth
= mh
->match
.lpm
.depth
;
2369 memcpy(ml
->lpm_ipv6
.ip
,
2370 mh
->match
.lpm
.ipv6
, sizeof(ml
->lpm_ipv6
.ip
));
2371 ml
->lpm_ipv6
.depth
= mh
->match
.lpm
.depth
;
2382 action_convert(struct rte_table_action
*a
,
2383 struct table_rule_action
*action
,
2384 struct rte_pipeline_table_entry
*data
)
2389 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_FWD
)) {
2390 status
= rte_table_action_apply(a
,
2392 RTE_TABLE_ACTION_FWD
,
2399 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_LB
)) {
2400 status
= rte_table_action_apply(a
,
2402 RTE_TABLE_ACTION_LB
,
2409 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_MTR
)) {
2410 status
= rte_table_action_apply(a
,
2412 RTE_TABLE_ACTION_MTR
,
2419 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_TM
)) {
2420 status
= rte_table_action_apply(a
,
2422 RTE_TABLE_ACTION_TM
,
2429 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_ENCAP
)) {
2430 status
= rte_table_action_apply(a
,
2432 RTE_TABLE_ACTION_ENCAP
,
2439 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_NAT
)) {
2440 status
= rte_table_action_apply(a
,
2442 RTE_TABLE_ACTION_NAT
,
2449 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_TTL
)) {
2450 status
= rte_table_action_apply(a
,
2452 RTE_TABLE_ACTION_TTL
,
2459 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_STATS
)) {
2460 status
= rte_table_action_apply(a
,
2462 RTE_TABLE_ACTION_STATS
,
2469 if (action
->action_mask
& (1LLU << RTE_TABLE_ACTION_TIME
)) {
2470 status
= rte_table_action_apply(a
,
2472 RTE_TABLE_ACTION_TIME
,
2482 static struct pipeline_msg_rsp
*
2483 pipeline_msg_handle_table_rule_add(struct pipeline_data
*p
,
2484 struct pipeline_msg_req
*req
)
2486 union table_rule_match_low_level match_ll
;
2487 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2488 struct table_rule_match
*match
= &req
->table_rule_add
.match
;
2489 struct table_rule_action
*action
= &req
->table_rule_add
.action
;
2490 struct rte_pipeline_table_entry
*data_in
, *data_out
;
2491 uint32_t table_id
= req
->id
;
2492 int key_found
, status
;
2493 struct rte_table_action
*a
= p
->table_data
[table_id
].a
;
2496 memset(p
->buffer
, 0, sizeof(p
->buffer
));
2497 data_in
= (struct rte_pipeline_table_entry
*) p
->buffer
;
2499 status
= match_convert(match
, &match_ll
, 1);
2505 status
= action_convert(a
, action
, data_in
);
2511 status
= rte_pipeline_table_entry_add(p
->p
,
2522 /* Write response */
2524 rsp
->table_rule_add
.data
= data_out
;
2529 static struct pipeline_msg_rsp
*
2530 pipeline_msg_handle_table_rule_add_default(struct pipeline_data
*p
,
2531 struct pipeline_msg_req
*req
)
2533 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2534 struct table_rule_action
*action
= &req
->table_rule_add_default
.action
;
2535 struct rte_pipeline_table_entry
*data_in
, *data_out
;
2536 uint32_t table_id
= req
->id
;
2540 memset(p
->buffer
, 0, sizeof(p
->buffer
));
2541 data_in
= (struct rte_pipeline_table_entry
*) p
->buffer
;
2543 data_in
->action
= action
->fwd
.action
;
2544 if (action
->fwd
.action
== RTE_PIPELINE_ACTION_PORT
)
2545 data_in
->port_id
= action
->fwd
.id
;
2546 if (action
->fwd
.action
== RTE_PIPELINE_ACTION_TABLE
)
2547 data_in
->table_id
= action
->fwd
.id
;
2549 /* Add default rule to table */
2550 status
= rte_pipeline_table_default_entry_add(p
->p
,
2559 /* Write response */
2561 rsp
->table_rule_add_default
.data
= data_out
;
2566 static struct pipeline_msg_rsp
*
2567 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data
*p
,
2568 struct pipeline_msg_req
*req
)
2571 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2573 uint32_t table_id
= req
->id
;
2574 struct table_rule_match
*match
= req
->table_rule_add_bulk
.match
;
2575 struct table_rule_action
*action
= req
->table_rule_add_bulk
.action
;
2576 struct rte_pipeline_table_entry
**data
=
2577 (struct rte_pipeline_table_entry
**)req
->table_rule_add_bulk
.data
;
2578 uint32_t n_rules
= req
->table_rule_add_bulk
.n_rules
;
2579 uint32_t bulk
= req
->table_rule_add_bulk
.bulk
;
2581 struct rte_table_action
*a
= p
->table_data
[table_id
].a
;
2582 union table_rule_match_low_level
*match_ll
;
2584 void **match_ll_ptr
;
2585 struct rte_pipeline_table_entry
**action_ll_ptr
;
2589 /* Memory allocation */
2590 match_ll
= calloc(n_rules
, sizeof(union table_rule_match_low_level
));
2591 action_ll
= calloc(n_rules
, TABLE_RULE_ACTION_SIZE_MAX
);
2592 match_ll_ptr
= calloc(n_rules
, sizeof(void *));
2594 calloc(n_rules
, sizeof(struct rte_pipeline_table_entry
*));
2595 found
= calloc(n_rules
, sizeof(int));
2597 if ((match_ll
== NULL
) ||
2598 (action_ll
== NULL
) ||
2599 (match_ll_ptr
== NULL
) ||
2600 (action_ll_ptr
== NULL
) ||
2604 for (i
= 0; i
< n_rules
; i
++) {
2605 match_ll_ptr
[i
] = (void *)&match_ll
[i
];
2607 (struct rte_pipeline_table_entry
*)&action_ll
[i
* TABLE_RULE_ACTION_SIZE_MAX
];
2610 /* Rule match conversion */
2611 for (i
= 0; i
< n_rules
; i
++) {
2612 status
= match_convert(&match
[i
], match_ll_ptr
[i
], 1);
2617 /* Rule action conversion */
2618 for (i
= 0; i
< n_rules
; i
++) {
2619 status
= action_convert(a
, &action
[i
], action_ll_ptr
[i
]);
2624 /* Add rule (match, action) to table */
2626 status
= rte_pipeline_table_entry_add_bulk(p
->p
,
2636 for (i
= 0; i
< n_rules
; i
++) {
2637 status
= rte_pipeline_table_entry_add(p
->p
,
2649 /* Write response */
2651 rsp
->table_rule_add_bulk
.n_rules
= n_rules
;
2655 free(action_ll_ptr
);
2664 free(action_ll_ptr
);
2670 rsp
->table_rule_add_bulk
.n_rules
= 0;
2674 static struct pipeline_msg_rsp
*
2675 pipeline_msg_handle_table_rule_delete(struct pipeline_data
*p
,
2676 struct pipeline_msg_req
*req
)
2678 union table_rule_match_low_level match_ll
;
2679 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2680 struct table_rule_match
*match
= &req
->table_rule_delete
.match
;
2681 uint32_t table_id
= req
->id
;
2682 int key_found
, status
;
2684 status
= match_convert(match
, &match_ll
, 0);
2690 rsp
->status
= rte_pipeline_table_entry_delete(p
->p
,
2699 static struct pipeline_msg_rsp
*
2700 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data
*p
,
2701 struct pipeline_msg_req
*req
)
2703 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2704 uint32_t table_id
= req
->id
;
2706 rsp
->status
= rte_pipeline_table_default_entry_delete(p
->p
,
2713 static struct pipeline_msg_rsp
*
2714 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data
*p
,
2715 struct pipeline_msg_req
*req
)
2717 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2718 uint32_t table_id
= req
->id
;
2719 void *data
= req
->table_rule_stats_read
.data
;
2720 int clear
= req
->table_rule_stats_read
.clear
;
2721 struct rte_table_action
*a
= p
->table_data
[table_id
].a
;
2723 rsp
->status
= rte_table_action_stats_read(a
,
2725 &rsp
->table_rule_stats_read
.stats
,
2731 static struct pipeline_msg_rsp
*
2732 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data
*p
,
2733 struct pipeline_msg_req
*req
)
2735 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2736 uint32_t table_id
= req
->id
;
2737 uint32_t meter_profile_id
= req
->table_mtr_profile_add
.meter_profile_id
;
2738 struct rte_table_action_meter_profile
*profile
=
2739 &req
->table_mtr_profile_add
.profile
;
2740 struct rte_table_action
*a
= p
->table_data
[table_id
].a
;
2742 rsp
->status
= rte_table_action_meter_profile_add(a
,
2749 static struct pipeline_msg_rsp
*
2750 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data
*p
,
2751 struct pipeline_msg_req
*req
)
2753 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2754 uint32_t table_id
= req
->id
;
2755 uint32_t meter_profile_id
=
2756 req
->table_mtr_profile_delete
.meter_profile_id
;
2757 struct rte_table_action
*a
= p
->table_data
[table_id
].a
;
2759 rsp
->status
= rte_table_action_meter_profile_delete(a
,
2765 static struct pipeline_msg_rsp
*
2766 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data
*p
,
2767 struct pipeline_msg_req
*req
)
2769 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2770 uint32_t table_id
= req
->id
;
2771 void *data
= req
->table_rule_mtr_read
.data
;
2772 uint32_t tc_mask
= req
->table_rule_mtr_read
.tc_mask
;
2773 int clear
= req
->table_rule_mtr_read
.clear
;
2774 struct rte_table_action
*a
= p
->table_data
[table_id
].a
;
2776 rsp
->status
= rte_table_action_meter_read(a
,
2779 &rsp
->table_rule_mtr_read
.stats
,
2785 static struct pipeline_msg_rsp
*
2786 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data
*p
,
2787 struct pipeline_msg_req
*req
)
2789 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2790 uint32_t table_id
= req
->id
;
2791 uint64_t dscp_mask
= req
->table_dscp_table_update
.dscp_mask
;
2792 struct rte_table_action_dscp_table
*dscp_table
=
2793 &req
->table_dscp_table_update
.dscp_table
;
2794 struct rte_table_action
*a
= p
->table_data
[table_id
].a
;
2796 rsp
->status
= rte_table_action_dscp_table_update(a
,
2803 static struct pipeline_msg_rsp
*
2804 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data
*p
,
2805 struct pipeline_msg_req
*req
)
2807 struct pipeline_msg_rsp
*rsp
= (struct pipeline_msg_rsp
*) req
;
2808 uint32_t table_id
= req
->id
;
2809 void *data
= req
->table_rule_ttl_read
.data
;
2810 int clear
= req
->table_rule_ttl_read
.clear
;
2811 struct rte_table_action
*a
= p
->table_data
[table_id
].a
;
2813 rsp
->status
= rte_table_action_ttl_read(a
,
2815 &rsp
->table_rule_ttl_read
.stats
,
2822 pipeline_msg_handle(struct pipeline_data
*p
)
2825 struct pipeline_msg_req
*req
;
2826 struct pipeline_msg_rsp
*rsp
;
2828 req
= pipeline_msg_recv(p
->msgq_req
);
2832 switch (req
->type
) {
2833 case PIPELINE_REQ_PORT_IN_STATS_READ
:
2834 rsp
= pipeline_msg_handle_port_in_stats_read(p
, req
);
2837 case PIPELINE_REQ_PORT_IN_ENABLE
:
2838 rsp
= pipeline_msg_handle_port_in_enable(p
, req
);
2841 case PIPELINE_REQ_PORT_IN_DISABLE
:
2842 rsp
= pipeline_msg_handle_port_in_disable(p
, req
);
2845 case PIPELINE_REQ_PORT_OUT_STATS_READ
:
2846 rsp
= pipeline_msg_handle_port_out_stats_read(p
, req
);
2849 case PIPELINE_REQ_TABLE_STATS_READ
:
2850 rsp
= pipeline_msg_handle_table_stats_read(p
, req
);
2853 case PIPELINE_REQ_TABLE_RULE_ADD
:
2854 rsp
= pipeline_msg_handle_table_rule_add(p
, req
);
2857 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT
:
2858 rsp
= pipeline_msg_handle_table_rule_add_default(p
, req
);
2861 case PIPELINE_REQ_TABLE_RULE_ADD_BULK
:
2862 rsp
= pipeline_msg_handle_table_rule_add_bulk(p
, req
);
2865 case PIPELINE_REQ_TABLE_RULE_DELETE
:
2866 rsp
= pipeline_msg_handle_table_rule_delete(p
, req
);
2869 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT
:
2870 rsp
= pipeline_msg_handle_table_rule_delete_default(p
, req
);
2873 case PIPELINE_REQ_TABLE_RULE_STATS_READ
:
2874 rsp
= pipeline_msg_handle_table_rule_stats_read(p
, req
);
2877 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD
:
2878 rsp
= pipeline_msg_handle_table_mtr_profile_add(p
, req
);
2881 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE
:
2882 rsp
= pipeline_msg_handle_table_mtr_profile_delete(p
, req
);
2885 case PIPELINE_REQ_TABLE_RULE_MTR_READ
:
2886 rsp
= pipeline_msg_handle_table_rule_mtr_read(p
, req
);
2889 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE
:
2890 rsp
= pipeline_msg_handle_table_dscp_table_update(p
, req
);
2893 case PIPELINE_REQ_TABLE_RULE_TTL_READ
:
2894 rsp
= pipeline_msg_handle_table_rule_ttl_read(p
, req
);
2898 rsp
= (struct pipeline_msg_rsp
*) req
;
2902 pipeline_msg_send(p
->msgq_rsp
, rsp
);
2907 * Data plane threads: main
2910 thread_main(void *arg __rte_unused
)
2912 struct thread_data
*t
;
2913 uint32_t thread_id
, i
;
2915 thread_id
= rte_lcore_id();
2916 t
= &thread_data
[thread_id
];
2919 for (i
= 0; ; i
++) {
2923 for (j
= 0; j
< t
->n_pipelines
; j
++)
2924 rte_pipeline_run(t
->p
[j
]);
2927 if ((i
& 0xF) == 0) {
2928 uint64_t time
= rte_get_tsc_cycles();
2929 uint64_t time_next_min
= UINT64_MAX
;
2931 if (time
< t
->time_next_min
)
2934 /* Pipeline message queues */
2935 for (j
= 0; j
< t
->n_pipelines
; j
++) {
2936 struct pipeline_data
*p
=
2937 &t
->pipeline_data
[j
];
2938 uint64_t time_next
= p
->time_next
;
2940 if (time_next
<= time
) {
2941 pipeline_msg_handle(p
);
2942 rte_pipeline_flush(p
->p
);
2943 time_next
= time
+ p
->timer_period
;
2944 p
->time_next
= time_next
;
2947 if (time_next
< time_next_min
)
2948 time_next_min
= time_next
;
2951 /* Thread message queues */
2953 uint64_t time_next
= t
->time_next
;
2955 if (time_next
<= time
) {
2956 thread_msg_handle(t
);
2957 time_next
= time
+ t
->timer_period
;
2958 t
->time_next
= time_next
;
2961 if (time_next
< time_next_min
)
2962 time_next_min
= time_next
;
2965 t
->time_next_min
= time_next_min
;