1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
6 #include <rte_pipeline.h>
9 #include <rte_hexdump.h>
10 #include "test_table.h"
11 #include "test_table_pipeline.h"
15 static rte_pipeline_port_out_action_handler port_action_0x00
16 (struct rte_mbuf
**pkts
, uint32_t n
, uint64_t *pkts_mask
, void *arg
);
17 static rte_pipeline_port_out_action_handler port_action_0xFF
18 (struct rte_mbuf
**pkts
, uint32_t n
, uint64_t *pkts_mask
, void *arg
);
19 static rte_pipeline_port_out_action_handler port_action_stub
20 (struct rte_mbuf
**pkts
, uint32_t n
, uint64_t *pkts_mask
, void *arg
);
23 rte_pipeline_port_out_action_handler
port_action_0x00(struct rte_mbuf
**pkts
,
31 printf("Port Action 0x00\n");
36 rte_pipeline_port_out_action_handler
port_action_0xFF(struct rte_mbuf
**pkts
,
44 printf("Port Action 0xFF\n");
49 rte_pipeline_port_out_action_handler
port_action_stub(struct rte_mbuf
**pkts
,
56 RTE_SET_USED(pkts_mask
);
58 printf("Port Action stub\n");
64 rte_pipeline_table_action_handler_hit
65 table_action_0x00(struct rte_pipeline
*p
, struct rte_mbuf
**pkts
,
66 uint64_t pkts_mask
, struct rte_pipeline_table_entry
**entry
, void *arg
);
68 rte_pipeline_table_action_handler_hit
69 table_action_stub_hit(struct rte_pipeline
*p
, struct rte_mbuf
**pkts
,
70 uint64_t pkts_mask
, struct rte_pipeline_table_entry
**entry
, void *arg
);
73 table_action_stub_miss(struct rte_pipeline
*p
, struct rte_mbuf
**pkts
,
74 uint64_t pkts_mask
, struct rte_pipeline_table_entry
*entry
, void *arg
);
76 rte_pipeline_table_action_handler_hit
77 table_action_0x00(__attribute__((unused
)) struct rte_pipeline
*p
,
78 __attribute__((unused
)) struct rte_mbuf
**pkts
,
80 __attribute__((unused
)) struct rte_pipeline_table_entry
**entry
,
81 __attribute__((unused
)) void *arg
)
83 printf("Table Action, setting pkts_mask to 0x00\n");
85 rte_pipeline_ah_packet_drop(p
, pkts_mask
);
89 rte_pipeline_table_action_handler_hit
90 table_action_stub_hit(__attribute__((unused
)) struct rte_pipeline
*p
,
91 __attribute__((unused
)) struct rte_mbuf
**pkts
,
93 __attribute__((unused
)) struct rte_pipeline_table_entry
**entry
,
94 __attribute__((unused
)) void *arg
)
96 printf("STUB Table Action Hit - doing nothing\n");
97 printf("STUB Table Action Hit - setting mask to 0x%"PRIx64
"\n",
99 pkts_mask
= (~override_hit_mask
) & 0x3;
100 rte_pipeline_ah_packet_drop(p
, pkts_mask
);
105 table_action_stub_miss(struct rte_pipeline
*p
,
106 __attribute__((unused
)) struct rte_mbuf
**pkts
,
108 __attribute__((unused
)) struct rte_pipeline_table_entry
*entry
,
109 __attribute__((unused
)) void *arg
)
111 printf("STUB Table Action Miss - setting mask to 0x%"PRIx64
"\n",
113 pkts_mask
= (~override_miss_mask
) & 0x3;
114 rte_pipeline_ah_packet_drop(p
, pkts_mask
);
130 char pipeline_test_names
[][64] = {
145 cleanup_pipeline(void)
148 rte_pipeline_free(p
);
154 static int check_pipeline_invalid_params(void);
157 check_pipeline_invalid_params(void)
159 struct rte_pipeline_params pipeline_params_1
= {
163 struct rte_pipeline_params pipeline_params_2
= {
167 struct rte_pipeline_params pipeline_params_3
= {
172 p
= rte_pipeline_create(NULL
);
174 RTE_LOG(INFO
, PIPELINE
,
175 "%s: configured pipeline with null params\n",
179 p
= rte_pipeline_create(&pipeline_params_1
);
181 RTE_LOG(INFO
, PIPELINE
, "%s: Configure pipeline with NULL "
186 p
= rte_pipeline_create(&pipeline_params_2
);
188 RTE_LOG(INFO
, PIPELINE
, "%s: Configure pipeline with invalid "
189 "socket\n", __func__
);
193 p
= rte_pipeline_create(&pipeline_params_3
);
195 RTE_LOG(INFO
, PIPELINE
, "%s: Configure pipeline with invalid "
196 "socket\n", __func__
);
200 /* Check pipeline consistency */
201 if (!rte_pipeline_check(p
)) {
202 rte_panic("Pipeline consistency reported as OK\n");
214 setup_pipeline(int test_type
)
218 struct rte_pipeline_params pipeline_params
= {
223 RTE_LOG(INFO
, PIPELINE
, "%s: **** Setting up %s test\n",
224 __func__
, pipeline_test_names
[test_type
]);
226 /* Pipeline configuration */
227 p
= rte_pipeline_create(&pipeline_params
);
229 RTE_LOG(INFO
, PIPELINE
, "%s: Failed to configure pipeline\n",
234 ret
= rte_pipeline_free(p
);
236 RTE_LOG(INFO
, PIPELINE
, "%s: Failed to free pipeline\n",
241 /* Pipeline configuration */
242 p
= rte_pipeline_create(&pipeline_params
);
244 RTE_LOG(INFO
, PIPELINE
, "%s: Failed to configure pipeline\n",
250 /* Input port configuration */
251 for (i
= 0; i
< N_PORTS
; i
++) {
252 struct rte_port_ring_reader_params port_ring_params
= {
256 struct rte_pipeline_port_in_params port_params
= {
257 .ops
= &rte_port_ring_reader_ops
,
258 .arg_create
= (void *) &port_ring_params
,
260 .burst_size
= BURST_SIZE
,
263 /* Put in action for some ports */
265 port_params
.f_action
= NULL
;
267 ret
= rte_pipeline_port_in_create(p
, &port_params
,
270 rte_panic("Unable to configure input port %d, ret:%d\n",
276 /* output Port configuration */
277 for (i
= 0; i
< N_PORTS
; i
++) {
278 struct rte_port_ring_writer_params port_ring_params
= {
280 .tx_burst_sz
= BURST_SIZE
,
283 struct rte_pipeline_port_out_params port_params
= {
284 .ops
= &rte_port_ring_writer_ops
,
285 .arg_create
= (void *) &port_ring_params
,
291 port_params
.f_action
= port_out_action
;
293 if (rte_pipeline_port_out_create(p
, &port_params
,
295 rte_panic("Unable to configure output port %d\n", i
);
300 /* Table configuration */
301 for (i
= 0; i
< N_PORTS
; i
++) {
302 struct rte_pipeline_table_params table_params
= {
303 .ops
= &rte_table_stub_ops
,
305 .f_action_hit
= action_handler_hit
,
306 .f_action_miss
= action_handler_miss
,
307 .action_data_size
= 0,
310 if (rte_pipeline_table_create(p
, &table_params
, &table_id
[i
])) {
311 rte_panic("Unable to configure table %u\n", i
);
315 if (connect_miss_action_to_table
)
316 if (rte_pipeline_table_create(p
, &table_params
,
318 rte_panic("Unable to configure table %u\n", i
);
323 for (i
= 0; i
< N_PORTS
; i
++)
324 if (rte_pipeline_port_in_connect_to_table(p
, port_in_id
[i
],
326 rte_panic("Unable to connect input port %u to "
327 "table %u\n", port_in_id
[i
], table_id
[i
]);
331 /* Add entries to tables */
332 for (i
= 0; i
< N_PORTS
; i
++) {
333 struct rte_pipeline_table_entry default_entry
= {
334 .action
= (enum rte_pipeline_action
)
335 table_entry_default_action
,
336 {.port_id
= port_out_id
[i
^1]},
338 struct rte_pipeline_table_entry
*default_entry_ptr
;
340 if (connect_miss_action_to_table
) {
341 printf("Setting first table to output to next table\n");
342 default_entry
.action
= RTE_PIPELINE_ACTION_TABLE
;
343 default_entry
.table_id
= table_id
[i
+2];
346 /* Add the default action for the table. */
347 ret
= rte_pipeline_table_default_entry_add(p
, table_id
[i
],
348 &default_entry
, &default_entry_ptr
);
350 rte_panic("Unable to add default entry to table %u "
351 "code %d\n", table_id
[i
], ret
);
354 printf("Added default entry to table id %d with "
356 table_id
[i
], default_entry
.action
);
358 if (connect_miss_action_to_table
) {
359 /* We create a second table so the first can pass
361 struct rte_pipeline_table_entry default_entry
= {
362 .action
= RTE_PIPELINE_ACTION_PORT
,
363 {.port_id
= port_out_id
[i
^1]},
365 printf("Setting secont table to output to port\n");
367 /* Add the default action for the table. */
368 ret
= rte_pipeline_table_default_entry_add(p
,
370 &default_entry
, &default_entry_ptr
);
372 rte_panic("Unable to add default entry to "
373 "table %u code %d\n",
377 printf("Added default entry to table id %d "
379 table_id
[i
], default_entry
.action
);
383 /* Enable input ports */
384 for (i
= 0; i
< N_PORTS
; i
++)
385 if (rte_pipeline_port_in_enable(p
, port_in_id
[i
]))
386 rte_panic("Unable to enable input port %u\n",
389 /* Check pipeline consistency */
390 if (rte_pipeline_check(p
) < 0) {
391 rte_panic("Pipeline consistency check failed\n");
394 printf("Pipeline Consistency OK!\n");
403 test_pipeline_single_filter(int test_type
, int expected_count
)
410 RTE_LOG(INFO
, PIPELINE
, "%s: **** Running %s test\n",
411 __func__
, pipeline_test_names
[test_type
]);
412 /* Run pipeline once */
413 for (i
= 0; i
< N_PORTS
; i
++)
417 ret
= rte_pipeline_flush(NULL
);
418 if (ret
!= -EINVAL
) {
419 RTE_LOG(INFO
, PIPELINE
,
420 "%s: No pipeline flush error NULL pipeline (%d)\n",
426 * Allocate a few mbufs and manually insert into the rings. */
427 for (i
= 0; i
< N_PORTS
; i
++)
428 for (j
= 0; j
< N_PORTS
; j
++) {
433 m
= rte_pktmbuf_alloc(pool
);
435 rte_panic("Failed to alloc mbuf from pool\n");
438 key
= RTE_MBUF_METADATA_UINT8_PTR(m
,
439 APP_METADATA_OFFSET(32));
441 k32
= (uint32_t *) key
;
442 k32
[0] = 0xadadadad >> (j
% 2);
444 RTE_LOG(INFO
, PIPELINE
, "%s: Enqueue onto ring %d\n",
446 rte_ring_enqueue(rings_rx
[i
], m
);
449 /* Run pipeline once */
450 for (i
= 0; i
< N_PORTS
; i
++)
454 * need to flush the pipeline, as there may be less hits than the burst
455 size and they will not have been flushed to the tx rings. */
456 rte_pipeline_flush(p
);
459 * Now we'll see what we got back on the tx rings. We should see whatever
460 * packets we had hits on that were destined for the output ports.
464 for (i
= 0; i
< N_PORTS
; i
++) {
465 void *objs
[RING_TX_SIZE
];
466 struct rte_mbuf
*mbuf
;
468 ret
= rte_ring_sc_dequeue_burst(rings_tx
[i
], objs
, 10, NULL
);
470 printf("Got no objects from ring %d - error code %d\n",
473 printf("Got %d object(s) from ring %d!\n", ret
, i
);
474 for (j
= 0; j
< ret
; j
++) {
476 rte_hexdump(stdout
, "Object:",
477 rte_pktmbuf_mtod(mbuf
, char *),
479 rte_pktmbuf_free(mbuf
);
485 if (tx_count
!= expected_count
) {
486 RTE_LOG(INFO
, PIPELINE
,
487 "%s: Unexpected packets out for %s test, expected %d, "
488 "got %d\n", __func__
, pipeline_test_names
[test_type
],
489 expected_count
, tx_count
);
502 test_table_pipeline(void)
504 /* TEST - All packets dropped */
505 action_handler_hit
= NULL
;
506 action_handler_miss
= NULL
;
507 table_entry_default_action
= RTE_PIPELINE_ACTION_DROP
;
508 setup_pipeline(e_TEST_STUB
);
509 if (test_pipeline_single_filter(e_TEST_STUB
, 0) < 0)
512 /* TEST - All packets passed through */
513 table_entry_default_action
= RTE_PIPELINE_ACTION_PORT
;
514 setup_pipeline(e_TEST_STUB
);
515 if (test_pipeline_single_filter(e_TEST_STUB
, 4) < 0)
518 /* TEST - one packet per port */
519 action_handler_hit
= NULL
;
520 action_handler_miss
= table_action_stub_miss
;
521 table_entry_default_action
= RTE_PIPELINE_ACTION_PORT
;
522 override_miss_mask
= 0x01; /* one packet per port */
523 setup_pipeline(e_TEST_STUB
);
524 if (test_pipeline_single_filter(e_TEST_STUB
, 2) < 0)
527 /* TEST - one packet per port */
528 override_miss_mask
= 0x02; /*all per port */
529 setup_pipeline(e_TEST_STUB
);
530 if (test_pipeline_single_filter(e_TEST_STUB
, 2) < 0)
533 /* TEST - all packets per port */
534 override_miss_mask
= 0x03; /*all per port */
535 setup_pipeline(e_TEST_STUB
);
536 if (test_pipeline_single_filter(e_TEST_STUB
, 4) < 0)
540 * This test will set up two tables in the pipeline. the first table
541 * will forward to another table on miss, and the second table will
544 connect_miss_action_to_table
= 1;
545 table_entry_default_action
= RTE_PIPELINE_ACTION_TABLE
;
546 action_handler_hit
= NULL
; /* not for stub, hitmask always zero */
547 action_handler_miss
= NULL
;
548 setup_pipeline(e_TEST_STUB
);
549 if (test_pipeline_single_filter(e_TEST_STUB
, 4) < 0)
551 connect_miss_action_to_table
= 0;
553 printf("TEST - two tables, hitmask override to 0x01\n");
554 connect_miss_action_to_table
= 1;
555 action_handler_miss
= table_action_stub_miss
;
556 override_miss_mask
= 0x01;
557 setup_pipeline(e_TEST_STUB
);
558 if (test_pipeline_single_filter(e_TEST_STUB
, 2) < 0)
560 connect_miss_action_to_table
= 0;
562 if (check_pipeline_invalid_params()) {
563 RTE_LOG(INFO
, PIPELINE
, "%s: Check pipeline invalid params "
564 "failed.\n", __func__
);