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(__rte_unused
struct rte_pipeline
*p
,
78 __rte_unused
struct rte_mbuf
**pkts
,
80 __rte_unused
struct rte_pipeline_table_entry
**entry
,
81 __rte_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(__rte_unused
struct rte_pipeline
*p
,
91 __rte_unused
struct rte_mbuf
**pkts
,
93 __rte_unused
struct rte_pipeline_table_entry
**entry
,
94 __rte_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 __rte_unused
struct rte_mbuf
**pkts
,
108 __rte_unused
struct rte_pipeline_table_entry
*entry
,
109 __rte_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 if (rte_eal_has_hugepages()) {
194 p
= rte_pipeline_create(&pipeline_params_3
);
196 RTE_LOG(INFO
, PIPELINE
, "%s: Configure pipeline with "
197 "invalid socket\n", __func__
);
202 /* Check pipeline consistency */
203 if (!rte_pipeline_check(p
)) {
204 rte_panic("Pipeline consistency reported as OK\n");
216 setup_pipeline(int test_type
)
220 struct rte_pipeline_params pipeline_params
= {
225 RTE_LOG(INFO
, PIPELINE
, "%s: **** Setting up %s test\n",
226 __func__
, pipeline_test_names
[test_type
]);
228 /* Pipeline configuration */
229 p
= rte_pipeline_create(&pipeline_params
);
231 RTE_LOG(INFO
, PIPELINE
, "%s: Failed to configure pipeline\n",
236 ret
= rte_pipeline_free(p
);
238 RTE_LOG(INFO
, PIPELINE
, "%s: Failed to free pipeline\n",
243 /* Pipeline configuration */
244 p
= rte_pipeline_create(&pipeline_params
);
246 RTE_LOG(INFO
, PIPELINE
, "%s: Failed to configure pipeline\n",
252 /* Input port configuration */
253 for (i
= 0; i
< N_PORTS
; i
++) {
254 struct rte_port_ring_reader_params port_ring_params
= {
258 struct rte_pipeline_port_in_params port_params
= {
259 .ops
= &rte_port_ring_reader_ops
,
260 .arg_create
= (void *) &port_ring_params
,
262 .burst_size
= BURST_SIZE
,
265 /* Put in action for some ports */
267 port_params
.f_action
= NULL
;
269 ret
= rte_pipeline_port_in_create(p
, &port_params
,
272 rte_panic("Unable to configure input port %d, ret:%d\n",
278 /* output Port configuration */
279 for (i
= 0; i
< N_PORTS
; i
++) {
280 struct rte_port_ring_writer_params port_ring_params
= {
282 .tx_burst_sz
= BURST_SIZE
,
285 struct rte_pipeline_port_out_params port_params
= {
286 .ops
= &rte_port_ring_writer_ops
,
287 .arg_create
= (void *) &port_ring_params
,
293 port_params
.f_action
= port_out_action
;
295 if (rte_pipeline_port_out_create(p
, &port_params
,
297 rte_panic("Unable to configure output port %d\n", i
);
302 /* Table configuration */
303 for (i
= 0; i
< N_PORTS
; i
++) {
304 struct rte_pipeline_table_params table_params
= {
305 .ops
= &rte_table_stub_ops
,
307 .f_action_hit
= action_handler_hit
,
308 .f_action_miss
= action_handler_miss
,
309 .action_data_size
= 0,
312 if (rte_pipeline_table_create(p
, &table_params
, &table_id
[i
])) {
313 rte_panic("Unable to configure table %u\n", i
);
317 if (connect_miss_action_to_table
)
318 if (rte_pipeline_table_create(p
, &table_params
,
320 rte_panic("Unable to configure table %u\n", i
);
325 for (i
= 0; i
< N_PORTS
; i
++)
326 if (rte_pipeline_port_in_connect_to_table(p
, port_in_id
[i
],
328 rte_panic("Unable to connect input port %u to "
329 "table %u\n", port_in_id
[i
], table_id
[i
]);
333 /* Add entries to tables */
334 for (i
= 0; i
< N_PORTS
; i
++) {
335 struct rte_pipeline_table_entry default_entry
= {
336 .action
= (enum rte_pipeline_action
)
337 table_entry_default_action
,
338 {.port_id
= port_out_id
[i
^1]},
340 struct rte_pipeline_table_entry
*default_entry_ptr
;
342 if (connect_miss_action_to_table
) {
343 printf("Setting first table to output to next table\n");
344 default_entry
.action
= RTE_PIPELINE_ACTION_TABLE
;
345 default_entry
.table_id
= table_id
[i
+2];
348 /* Add the default action for the table. */
349 ret
= rte_pipeline_table_default_entry_add(p
, table_id
[i
],
350 &default_entry
, &default_entry_ptr
);
352 rte_panic("Unable to add default entry to table %u "
353 "code %d\n", table_id
[i
], ret
);
356 printf("Added default entry to table id %d with "
358 table_id
[i
], default_entry
.action
);
360 if (connect_miss_action_to_table
) {
361 /* We create a second table so the first can pass
363 struct rte_pipeline_table_entry default_entry
= {
364 .action
= RTE_PIPELINE_ACTION_PORT
,
365 {.port_id
= port_out_id
[i
^1]},
367 printf("Setting secont table to output to port\n");
369 /* Add the default action for the table. */
370 ret
= rte_pipeline_table_default_entry_add(p
,
372 &default_entry
, &default_entry_ptr
);
374 rte_panic("Unable to add default entry to "
375 "table %u code %d\n",
379 printf("Added default entry to table id %d "
381 table_id
[i
], default_entry
.action
);
385 /* Enable input ports */
386 for (i
= 0; i
< N_PORTS
; i
++)
387 if (rte_pipeline_port_in_enable(p
, port_in_id
[i
]))
388 rte_panic("Unable to enable input port %u\n",
391 /* Check pipeline consistency */
392 if (rte_pipeline_check(p
) < 0) {
393 rte_panic("Pipeline consistency check failed\n");
396 printf("Pipeline Consistency OK!\n");
405 test_pipeline_single_filter(int test_type
, int expected_count
)
412 RTE_LOG(INFO
, PIPELINE
, "%s: **** Running %s test\n",
413 __func__
, pipeline_test_names
[test_type
]);
414 /* Run pipeline once */
415 for (i
= 0; i
< N_PORTS
; i
++)
419 ret
= rte_pipeline_flush(NULL
);
420 if (ret
!= -EINVAL
) {
421 RTE_LOG(INFO
, PIPELINE
,
422 "%s: No pipeline flush error NULL pipeline (%d)\n",
428 * Allocate a few mbufs and manually insert into the rings. */
429 for (i
= 0; i
< N_PORTS
; i
++)
430 for (j
= 0; j
< N_PORTS
; j
++) {
435 m
= rte_pktmbuf_alloc(pool
);
437 rte_panic("Failed to alloc mbuf from pool\n");
440 key
= RTE_MBUF_METADATA_UINT8_PTR(m
,
441 APP_METADATA_OFFSET(32));
443 k32
= (uint32_t *) key
;
444 k32
[0] = 0xadadadad >> (j
% 2);
446 RTE_LOG(INFO
, PIPELINE
, "%s: Enqueue onto ring %d\n",
448 rte_ring_enqueue(rings_rx
[i
], m
);
451 /* Run pipeline once */
452 for (i
= 0; i
< N_PORTS
; i
++)
456 * need to flush the pipeline, as there may be less hits than the burst
457 size and they will not have been flushed to the tx rings. */
458 rte_pipeline_flush(p
);
461 * Now we'll see what we got back on the tx rings. We should see whatever
462 * packets we had hits on that were destined for the output ports.
466 for (i
= 0; i
< N_PORTS
; i
++) {
467 void *objs
[RING_TX_SIZE
];
468 struct rte_mbuf
*mbuf
;
470 ret
= rte_ring_sc_dequeue_burst(rings_tx
[i
], objs
, 10, NULL
);
472 printf("Got no objects from ring %d - error code %d\n",
475 printf("Got %d object(s) from ring %d!\n", ret
, i
);
476 for (j
= 0; j
< ret
; j
++) {
478 rte_hexdump(stdout
, "Object:",
479 rte_pktmbuf_mtod(mbuf
, char *),
481 rte_pktmbuf_free(mbuf
);
487 if (tx_count
!= expected_count
) {
488 RTE_LOG(INFO
, PIPELINE
,
489 "%s: Unexpected packets out for %s test, expected %d, "
490 "got %d\n", __func__
, pipeline_test_names
[test_type
],
491 expected_count
, tx_count
);
504 test_table_pipeline(void)
506 /* TEST - All packets dropped */
507 action_handler_hit
= NULL
;
508 action_handler_miss
= NULL
;
509 table_entry_default_action
= RTE_PIPELINE_ACTION_DROP
;
510 setup_pipeline(e_TEST_STUB
);
511 if (test_pipeline_single_filter(e_TEST_STUB
, 0) < 0)
514 /* TEST - All packets passed through */
515 table_entry_default_action
= RTE_PIPELINE_ACTION_PORT
;
516 setup_pipeline(e_TEST_STUB
);
517 if (test_pipeline_single_filter(e_TEST_STUB
, 4) < 0)
520 /* TEST - one packet per port */
521 action_handler_hit
= NULL
;
522 action_handler_miss
= table_action_stub_miss
;
523 table_entry_default_action
= RTE_PIPELINE_ACTION_PORT
;
524 override_miss_mask
= 0x01; /* one packet per port */
525 setup_pipeline(e_TEST_STUB
);
526 if (test_pipeline_single_filter(e_TEST_STUB
, 2) < 0)
529 /* TEST - one packet per port */
530 override_miss_mask
= 0x02; /*all per port */
531 setup_pipeline(e_TEST_STUB
);
532 if (test_pipeline_single_filter(e_TEST_STUB
, 2) < 0)
535 /* TEST - all packets per port */
536 override_miss_mask
= 0x03; /*all per port */
537 setup_pipeline(e_TEST_STUB
);
538 if (test_pipeline_single_filter(e_TEST_STUB
, 4) < 0)
542 * This test will set up two tables in the pipeline. the first table
543 * will forward to another table on miss, and the second table will
546 connect_miss_action_to_table
= 1;
547 table_entry_default_action
= RTE_PIPELINE_ACTION_TABLE
;
548 action_handler_hit
= NULL
; /* not for stub, hitmask always zero */
549 action_handler_miss
= NULL
;
550 setup_pipeline(e_TEST_STUB
);
551 if (test_pipeline_single_filter(e_TEST_STUB
, 4) < 0)
553 connect_miss_action_to_table
= 0;
555 printf("TEST - two tables, hitmask override to 0x01\n");
556 connect_miss_action_to_table
= 1;
557 action_handler_miss
= table_action_stub_miss
;
558 override_miss_mask
= 0x01;
559 setup_pipeline(e_TEST_STUB
);
560 if (test_pipeline_single_filter(e_TEST_STUB
, 2) < 0)
562 connect_miss_action_to_table
= 0;
564 if (check_pipeline_invalid_params()) {
565 RTE_LOG(INFO
, PIPELINE
, "%s: Check pipeline invalid params "
566 "failed.\n", __func__
);