xref: /dpdk/app/test-pipeline/pipeline_lpm.c (revision f6897b23f70b84742129a215ea2be17c8843adb8)
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