1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2016 Intel Corporation
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8
9 #include <rte_log.h>
10 #include <rte_ethdev.h>
11 #include <rte_ether.h>
12 #include <rte_ip.h>
13 #include <rte_byteorder.h>
14
15 #include <rte_port_ring.h>
16 #include <rte_table_lpm.h>
17 #include <rte_pipeline.h>
18
19 #include "main.h"
20
21 #ifndef PIPELINE_LPM_TABLE_NUMBER_TABLE8s
22 #define PIPELINE_LPM_TABLE_NUMBER_TABLE8s 256
23 #endif
24
25 void
app_main_loop_worker_pipeline_lpm(void)26 app_main_loop_worker_pipeline_lpm(void) {
27 struct rte_pipeline_params pipeline_params = {
28 .name = "pipeline",
29 .socket_id = rte_socket_id(),
30 };
31
32 struct rte_pipeline *p;
33 uint32_t port_in_id[APP_MAX_PORTS];
34 uint32_t port_out_id[APP_MAX_PORTS];
35 uint32_t table_id;
36 uint32_t i;
37
38 RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with "
39 "LPM table)\n", rte_lcore_id());
40
41 /* Pipeline configuration */
42 p = rte_pipeline_create(&pipeline_params);
43 if (p == NULL)
44 rte_panic("Unable to configure the pipeline\n");
45
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],
50 };
51
52 struct rte_pipeline_port_in_params port_params = {
53 .ops = &rte_port_ring_reader_ops,
54 .arg_create = (void *) &port_ring_params,
55 .f_action = NULL,
56 .arg_ah = NULL,
57 .burst_size = app.burst_size_worker_read,
58 };
59
60 if (rte_pipeline_port_in_create(p, &port_params,
61 &port_in_id[i]))
62 rte_panic("Unable to configure input port for "
63 "ring %d\n", i);
64 }
65
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,
71 };
72
73 struct rte_pipeline_port_out_params port_params = {
74 .ops = &rte_port_ring_writer_ops,
75 .arg_create = (void *) &port_ring_params,
76 .f_action = NULL,
77 .arg_ah = NULL,
78 };
79
80 if (rte_pipeline_port_out_create(p, &port_params,
81 &port_out_id[i]))
82 rte_panic("Unable to configure output port for "
83 "ring %d\n", i);
84 }
85
86 /* Table configuration */
87 {
88 struct rte_table_lpm_params table_lpm_params = {
89 .name = "LPM",
90 .n_rules = 1 << 24,
91 .number_tbl8s = PIPELINE_LPM_TABLE_NUMBER_TABLE8s,
92 .flags = 0,
93 .entry_unique_size =
94 sizeof(struct rte_pipeline_table_entry),
95 .offset = APP_METADATA_OFFSET(32),
96 };
97
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,
103 .arg_ah = NULL,
104 .action_data_size = 0,
105 };
106
107 if (rte_pipeline_table_create(p, &table_params, &table_id))
108 rte_panic("Unable to configure the LPM table\n");
109 }
110
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],
114 table_id))
115 rte_panic("Unable to connect input port %u to "
116 "table %u\n", port_in_id[i], table_id);
117
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)]},
123 };
124
125 struct rte_table_lpm_key key = {
126 .ip = i << (24 - rte_popcount32(app.n_ports - 1)),
127 .depth = 8 + rte_popcount32(app.n_ports - 1),
128 };
129
130 struct rte_pipeline_table_entry *entry_ptr;
131
132 int key_found, status;
133
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,
140 key.ip & 0x000000FF,
141 key.depth,
142 i);
143
144 status = rte_pipeline_table_entry_add(p, table_id, &key, &entry,
145 &key_found, &entry_ptr);
146 if (status < 0)
147 rte_panic("Unable to add entry to table %u (%d)\n",
148 table_id, status);
149 }
150
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",
155 port_in_id[i]);
156
157 /* Check pipeline consistency */
158 if (rte_pipeline_check(p) < 0)
159 rte_panic("Pipeline consistency check failed\n");
160
161 /* Run-time */
162 #if APP_FLUSH == 0
163 while (!force_quit)
164 rte_pipeline_run(p);
165 #else
166 i = 0;
167 while (!force_quit) {
168 rte_pipeline_run(p);
169
170 if ((i & APP_FLUSH) == 0)
171 rte_pipeline_flush(p);
172 i++;
173 }
174 #endif
175 }
176