Branch data Line data Source code
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_acl.h>
17 : : #include <rte_pipeline.h>
18 : :
19 : : #include "main.h"
20 : :
21 : : enum {
22 : : PROTO_FIELD_IPV4,
23 : : SRC_FIELD_IPV4,
24 : : DST_FIELD_IPV4,
25 : : SRCP_FIELD_IPV4,
26 : : DSTP_FIELD_IPV4,
27 : : NUM_FIELDS_IPV4
28 : : };
29 : :
30 : : /*
31 : : * Here we define the 'shape' of the data we're searching for,
32 : : * by defining the meta-data of the ACL rules.
33 : : * in this case, we're defining 5 tuples. IP addresses, ports,
34 : : * and protocol.
35 : : */
36 : : struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = {
37 : : {
38 : : .type = RTE_ACL_FIELD_TYPE_BITMASK,
39 : : .size = sizeof(uint8_t),
40 : : .field_index = PROTO_FIELD_IPV4,
41 : : .input_index = PROTO_FIELD_IPV4,
42 : : .offset = sizeof(struct rte_ether_hdr) +
43 : : offsetof(struct rte_ipv4_hdr, next_proto_id),
44 : : },
45 : : {
46 : : .type = RTE_ACL_FIELD_TYPE_MASK,
47 : : .size = sizeof(uint32_t),
48 : : .field_index = SRC_FIELD_IPV4,
49 : : .input_index = SRC_FIELD_IPV4,
50 : : .offset = sizeof(struct rte_ether_hdr) +
51 : : offsetof(struct rte_ipv4_hdr, src_addr),
52 : : },
53 : : {
54 : : .type = RTE_ACL_FIELD_TYPE_MASK,
55 : : .size = sizeof(uint32_t),
56 : : .field_index = DST_FIELD_IPV4,
57 : : .input_index = DST_FIELD_IPV4,
58 : : .offset = sizeof(struct rte_ether_hdr) +
59 : : offsetof(struct rte_ipv4_hdr, dst_addr),
60 : : },
61 : : {
62 : : .type = RTE_ACL_FIELD_TYPE_RANGE,
63 : : .size = sizeof(uint16_t),
64 : : .field_index = SRCP_FIELD_IPV4,
65 : : .input_index = SRCP_FIELD_IPV4,
66 : : .offset = sizeof(struct rte_ether_hdr) +
67 : : sizeof(struct rte_ipv4_hdr),
68 : : },
69 : : {
70 : : .type = RTE_ACL_FIELD_TYPE_RANGE,
71 : : .size = sizeof(uint16_t),
72 : : .field_index = DSTP_FIELD_IPV4,
73 : : .input_index = SRCP_FIELD_IPV4,
74 : : .offset = sizeof(struct rte_ether_hdr) +
75 : : sizeof(struct rte_ipv4_hdr) + sizeof(uint16_t),
76 : : },
77 : : };
78 : :
79 : :
80 : :
81 : : void
82 : 0 : app_main_loop_worker_pipeline_acl(void) {
83 : 0 : struct rte_pipeline_params pipeline_params = {
84 : : .name = "pipeline",
85 : 0 : .socket_id = rte_socket_id(),
86 : : };
87 : :
88 : : struct rte_pipeline *p;
89 : : uint32_t port_in_id[APP_MAX_PORTS];
90 : : uint32_t port_out_id[APP_MAX_PORTS];
91 : : uint32_t table_id;
92 : : uint32_t i;
93 : :
94 : 0 : RTE_LOG(INFO, USER1,
95 : : "Core %u is doing work (pipeline with ACL table)\n",
96 : : rte_lcore_id());
97 : :
98 : : /* Pipeline configuration */
99 : 0 : p = rte_pipeline_create(&pipeline_params);
100 : 0 : if (p == NULL)
101 : 0 : rte_panic("Unable to configure the pipeline\n");
102 : :
103 : : /* Input port configuration */
104 : 0 : for (i = 0; i < app.n_ports; i++) {
105 : 0 : struct rte_port_ring_reader_params port_ring_params = {
106 : 0 : .ring = app.rings_rx[i],
107 : : };
108 : :
109 : 0 : struct rte_pipeline_port_in_params port_params = {
110 : : .ops = &rte_port_ring_reader_ops,
111 : : .arg_create = (void *) &port_ring_params,
112 : : .f_action = NULL,
113 : : .arg_ah = NULL,
114 : 0 : .burst_size = app.burst_size_worker_read,
115 : : };
116 : :
117 : 0 : if (rte_pipeline_port_in_create(p, &port_params,
118 : : &port_in_id[i]))
119 : 0 : rte_panic("Unable to configure input port for "
120 : : "ring %d\n", i);
121 : : }
122 : :
123 : : /* Output port configuration */
124 : 0 : for (i = 0; i < app.n_ports; i++) {
125 : 0 : struct rte_port_ring_writer_params port_ring_params = {
126 : 0 : .ring = app.rings_tx[i],
127 : 0 : .tx_burst_sz = app.burst_size_worker_write,
128 : : };
129 : :
130 : 0 : struct rte_pipeline_port_out_params port_params = {
131 : : .ops = &rte_port_ring_writer_ops,
132 : : .arg_create = (void *) &port_ring_params,
133 : : .f_action = NULL,
134 : : .arg_ah = NULL,
135 : : };
136 : :
137 : 0 : if (rte_pipeline_port_out_create(p, &port_params,
138 : : &port_out_id[i]))
139 : 0 : rte_panic("Unable to configure output port for "
140 : : "ring %d\n", i);
141 : : }
142 : :
143 : : /* Table configuration */
144 : : {
145 : 0 : struct rte_table_acl_params table_acl_params = {
146 : : .name = "test", /* unique identifier for acl contexts */
147 : : .n_rules = 1 << 5,
148 : : .n_rule_fields = DIM(ipv4_field_formats),
149 : : };
150 : :
151 : : /* Copy in the rule meta-data defined above into the params */
152 : : memcpy(table_acl_params.field_format, ipv4_field_formats,
153 : : sizeof(ipv4_field_formats));
154 : :
155 : 0 : struct rte_pipeline_table_params table_params = {
156 : : .ops = &rte_table_acl_ops,
157 : : .arg_create = &table_acl_params,
158 : : .f_action_hit = NULL,
159 : : .f_action_miss = NULL,
160 : : .arg_ah = NULL,
161 : : .action_data_size = 0,
162 : : };
163 : :
164 : 0 : if (rte_pipeline_table_create(p, &table_params, &table_id))
165 : 0 : rte_panic("Unable to configure the ACL table\n");
166 : : }
167 : :
168 : : /* Interconnecting ports and tables */
169 : 0 : for (i = 0; i < app.n_ports; i++)
170 : 0 : if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
171 : : table_id))
172 : 0 : rte_panic("Unable to connect input port %u to "
173 : : "table %u\n", port_in_id[i], table_id);
174 : :
175 : : /* Add entries to tables */
176 : 0 : for (i = 0; i < app.n_ports; i++) {
177 : 0 : struct rte_pipeline_table_entry table_entry = {
178 : : .action = RTE_PIPELINE_ACTION_PORT,
179 : 0 : {.port_id = port_out_id[i & (app.n_ports - 1)]},
180 : : };
181 : : struct rte_table_acl_rule_add_params rule_params;
182 : : struct rte_pipeline_table_entry *entry_ptr;
183 : : int key_found, ret;
184 : :
185 : : memset(&rule_params, 0, sizeof(rule_params));
186 : :
187 : : /* Set the rule values */
188 : : rule_params.field_value[SRC_FIELD_IPV4].value.u32 = 0;
189 : : rule_params.field_value[SRC_FIELD_IPV4].mask_range.u32 = 0;
190 : 0 : rule_params.field_value[DST_FIELD_IPV4].value.u32 =
191 : 0 : i << (24 - rte_popcount32(app.n_ports - 1));
192 : 0 : rule_params.field_value[DST_FIELD_IPV4].mask_range.u32 =
193 : 0 : 8 + rte_popcount32(app.n_ports - 1);
194 : : rule_params.field_value[SRCP_FIELD_IPV4].value.u16 = 0;
195 : 0 : rule_params.field_value[SRCP_FIELD_IPV4].mask_range.u16 =
196 : : UINT16_MAX;
197 : : rule_params.field_value[DSTP_FIELD_IPV4].value.u16 = 0;
198 : 0 : rule_params.field_value[DSTP_FIELD_IPV4].mask_range.u16 =
199 : : UINT16_MAX;
200 : : rule_params.field_value[PROTO_FIELD_IPV4].value.u8 = 0;
201 : : rule_params.field_value[PROTO_FIELD_IPV4].mask_range.u8 = 0;
202 : :
203 : : rule_params.priority = 0;
204 : :
205 : : uint32_t dst_addr = rule_params.field_value[DST_FIELD_IPV4].
206 : : value.u32;
207 : : uint32_t dst_mask =
208 : : rule_params.field_value[DST_FIELD_IPV4].mask_range.u32;
209 : :
210 : 0 : printf("Adding rule to ACL table (IPv4 destination = "
211 : : "%u.%u.%u.%u/%u => port out = %u)\n",
212 : : (dst_addr & 0xFF000000) >> 24,
213 : 0 : (dst_addr & 0x00FF0000) >> 16,
214 : 0 : (dst_addr & 0x0000FF00) >> 8,
215 : : dst_addr & 0x000000FF,
216 : : dst_mask,
217 : : table_entry.port_id);
218 : :
219 : : /* For ACL, add needs an rte_table_acl_rule_add_params struct */
220 : 0 : ret = rte_pipeline_table_entry_add(p, table_id, &rule_params,
221 : : &table_entry, &key_found, &entry_ptr);
222 : 0 : if (ret < 0)
223 : 0 : rte_panic("Unable to add entry to table %u (%d)\n",
224 : : table_id, ret);
225 : : }
226 : :
227 : : /* Enable input ports */
228 : 0 : for (i = 0; i < app.n_ports; i++)
229 : 0 : if (rte_pipeline_port_in_enable(p, port_in_id[i]))
230 : 0 : rte_panic("Unable to enable input port %u\n",
231 : : port_in_id[i]);
232 : :
233 : : /* Check pipeline consistency */
234 : 0 : if (rte_pipeline_check(p) < 0)
235 : 0 : rte_panic("Pipeline consistency check failed\n");
236 : :
237 : : /* Run-time */
238 : : #if APP_FLUSH == 0
239 : 0 : while (!force_quit)
240 : 0 : rte_pipeline_run(p);
241 : : #else
242 : : i = 0;
243 : : while (!force_quit) {
244 : : rte_pipeline_run(p);
245 : :
246 : : if ((i & APP_FLUSH) == 0)
247 : : rte_pipeline_flush(p);
248 : : i++;
249 : : }
250 : : #endif
251 : 0 : }
|