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__);