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