1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
10 #include <rte_ethdev.h>
11 #include <rte_ether.h>
13 #include <rte_byteorder.h>
15 #include <rte_port_ring.h>
16 #include <rte_table_lpm.h>
17 #include <rte_pipeline.h>
21 #ifndef PIPELINE_LPM_TABLE_NUMBER_TABLE8s
22 #define PIPELINE_LPM_TABLE_NUMBER_TABLE8s 256
26 app_main_loop_worker_pipeline_lpm(void) {
27 struct rte_pipeline_params pipeline_params = {
29 .socket_id = rte_socket_id(),
32 struct rte_pipeline *p;
33 uint32_t port_in_id[APP_MAX_PORTS];
34 uint32_t port_out_id[APP_MAX_PORTS];
38 RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with "
39 "LPM table)\n", rte_lcore_id());
41 /* Pipeline configuration */
42 p = rte_pipeline_create(&pipeline_params);
44 rte_panic("Unable to configure the pipeline\n");
46 /* Input port configuration */
47 for (i = 0; i < app.n_ports; i++) {
48 struct rte_port_ring_reader_params port_ring_params = {
49 .ring = app.rings_rx[i],
52 struct rte_pipeline_port_in_params port_params = {
53 .ops = &rte_port_ring_reader_ops,
54 .arg_create = (void *) &port_ring_params,
57 .burst_size = app.burst_size_worker_read,
60 if (rte_pipeline_port_in_create(p, &port_params,
62 rte_panic("Unable to configure input port for "
66 /* Output port configuration */
67 for (i = 0; i < app.n_ports; i++) {
68 struct rte_port_ring_writer_params port_ring_params = {
69 .ring = app.rings_tx[i],
70 .tx_burst_sz = app.burst_size_worker_write,
73 struct rte_pipeline_port_out_params port_params = {
74 .ops = &rte_port_ring_writer_ops,
75 .arg_create = (void *) &port_ring_params,
80 if (rte_pipeline_port_out_create(p, &port_params,
82 rte_panic("Unable to configure output port for "
86 /* Table configuration */
88 struct rte_table_lpm_params table_lpm_params = {
91 .number_tbl8s = PIPELINE_LPM_TABLE_NUMBER_TABLE8s,
94 sizeof(struct rte_pipeline_table_entry),
95 .offset = APP_METADATA_OFFSET(32),
98 struct rte_pipeline_table_params table_params = {
99 .ops = &rte_table_lpm_ops,
100 .arg_create = &table_lpm_params,
101 .f_action_hit = NULL,
102 .f_action_miss = NULL,
104 .action_data_size = 0,
107 if (rte_pipeline_table_create(p, &table_params, &table_id))
108 rte_panic("Unable to configure the LPM table\n");
111 /* Interconnecting ports and tables */
112 for (i = 0; i < app.n_ports; i++)
113 if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
115 rte_panic("Unable to connect input port %u to "
116 "table %u\n", port_in_id[i], table_id);
118 /* Add entries to tables */
119 for (i = 0; i < app.n_ports; i++) {
120 struct rte_pipeline_table_entry entry = {
121 .action = RTE_PIPELINE_ACTION_PORT,
122 {.port_id = port_out_id[i & (app.n_ports - 1)]},
125 struct rte_table_lpm_key key = {
126 .ip = i << (24 - __builtin_popcount(app.n_ports - 1)),
127 .depth = 8 + __builtin_popcount(app.n_ports - 1),
130 struct rte_pipeline_table_entry *entry_ptr;
132 int key_found, status;
134 printf("Adding rule to LPM table (IPv4 destination = %"
135 PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32 "/%" PRIu8
136 " => port out = %" PRIu32 ")\n",
137 (key.ip & 0xFF000000) >> 24,
138 (key.ip & 0x00FF0000) >> 16,
139 (key.ip & 0x0000FF00) >> 8,
144 status = rte_pipeline_table_entry_add(p, table_id, &key, &entry,
145 &key_found, &entry_ptr);
147 rte_panic("Unable to add entry to table %u (%d)\n",
151 /* Enable input ports */
152 for (i = 0; i < app.n_ports; i++)
153 if (rte_pipeline_port_in_enable(p, port_in_id[i]))
154 rte_panic("Unable to enable input port %u\n",
157 /* Check pipeline consistency */
158 if (rte_pipeline_check(p) < 0)
159 rte_panic("Pipeline consistency check failed\n");
169 if ((i & APP_FLUSH) == 0)
170 rte_pipeline_flush(p);