]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2016 Intel Corporation | |
7c673cae FG |
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, | |
f67539c2 TL |
42 | .offset = sizeof(struct rte_ether_hdr) + |
43 | offsetof(struct rte_ipv4_hdr, next_proto_id), | |
7c673cae FG |
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, | |
f67539c2 TL |
50 | .offset = sizeof(struct rte_ether_hdr) + |
51 | offsetof(struct rte_ipv4_hdr, src_addr), | |
7c673cae FG |
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, | |
f67539c2 TL |
58 | .offset = sizeof(struct rte_ether_hdr) + |
59 | offsetof(struct rte_ipv4_hdr, dst_addr), | |
7c673cae FG |
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, | |
f67539c2 TL |
66 | .offset = sizeof(struct rte_ether_hdr) + |
67 | sizeof(struct rte_ipv4_hdr), | |
7c673cae FG |
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, | |
f67539c2 TL |
74 | .offset = sizeof(struct rte_ether_hdr) + |
75 | sizeof(struct rte_ipv4_hdr) + sizeof(uint16_t), | |
7c673cae FG |
76 | }, |
77 | }; | |
78 | ||
79 | ||
80 | ||
81 | void | |
82 | app_main_loop_worker_pipeline_acl(void) { | |
83 | struct rte_pipeline_params pipeline_params = { | |
84 | .name = "pipeline", | |
85 | .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 | RTE_LOG(INFO, USER1, | |
95 | "Core %u is doing work (pipeline with ACL table)\n", | |
96 | rte_lcore_id()); | |
97 | ||
98 | /* Pipeline configuration */ | |
99 | p = rte_pipeline_create(&pipeline_params); | |
100 | if (p == NULL) | |
101 | rte_panic("Unable to configure the pipeline\n"); | |
102 | ||
103 | /* Input port configuration */ | |
104 | for (i = 0; i < app.n_ports; i++) { | |
105 | struct rte_port_ring_reader_params port_ring_params = { | |
106 | .ring = app.rings_rx[i], | |
107 | }; | |
108 | ||
109 | 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 | .burst_size = app.burst_size_worker_read, | |
115 | }; | |
116 | ||
117 | if (rte_pipeline_port_in_create(p, &port_params, | |
118 | &port_in_id[i])) | |
119 | rte_panic("Unable to configure input port for " | |
120 | "ring %d\n", i); | |
121 | } | |
122 | ||
123 | /* Output port configuration */ | |
124 | for (i = 0; i < app.n_ports; i++) { | |
125 | struct rte_port_ring_writer_params port_ring_params = { | |
126 | .ring = app.rings_tx[i], | |
127 | .tx_burst_sz = app.burst_size_worker_write, | |
128 | }; | |
129 | ||
130 | 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 | if (rte_pipeline_port_out_create(p, &port_params, | |
138 | &port_out_id[i])) | |
139 | rte_panic("Unable to configure output port for " | |
140 | "ring %d\n", i); | |
141 | } | |
142 | ||
143 | /* Table configuration */ | |
144 | { | |
145 | 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 | 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 | if (rte_pipeline_table_create(p, &table_params, &table_id)) | |
165 | rte_panic("Unable to configure the ACL table\n"); | |
166 | } | |
167 | ||
168 | /* Interconnecting ports and tables */ | |
169 | for (i = 0; i < app.n_ports; i++) | |
170 | if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], | |
171 | table_id)) | |
172 | 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 | for (i = 0; i < app.n_ports; i++) { | |
177 | struct rte_pipeline_table_entry table_entry = { | |
178 | .action = RTE_PIPELINE_ACTION_PORT, | |
179 | {.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 | rule_params.field_value[DST_FIELD_IPV4].value.u32 = | |
191 | i << (24 - __builtin_popcount(app.n_ports - 1)); | |
192 | rule_params.field_value[DST_FIELD_IPV4].mask_range.u32 = | |
193 | 8 + __builtin_popcount(app.n_ports - 1); | |
194 | rule_params.field_value[SRCP_FIELD_IPV4].value.u16 = 0; | |
195 | 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 | 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 | printf("Adding rule to ACL table (IPv4 destination = " | |
211 | "%u.%u.%u.%u/%u => port out = %u)\n", | |
212 | (dst_addr & 0xFF000000) >> 24, | |
213 | (dst_addr & 0x00FF0000) >> 16, | |
214 | (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 | ret = rte_pipeline_table_entry_add(p, table_id, &rule_params, | |
221 | &table_entry, &key_found, &entry_ptr); | |
222 | if (ret < 0) | |
223 | rte_panic("Unable to add entry to table %u (%d)\n", | |
224 | table_id, ret); | |
225 | } | |
226 | ||
227 | /* Enable input ports */ | |
228 | for (i = 0; i < app.n_ports; i++) | |
229 | if (rte_pipeline_port_in_enable(p, port_in_id[i])) | |
230 | rte_panic("Unable to enable input port %u\n", | |
231 | port_in_id[i]); | |
232 | ||
233 | /* Check pipeline consistency */ | |
234 | if (rte_pipeline_check(p) < 0) | |
235 | rte_panic("Pipeline consistency check failed\n"); | |
236 | ||
237 | /* Run-time */ | |
238 | #if APP_FLUSH == 0 | |
239 | for ( ; ; ) | |
240 | rte_pipeline_run(p); | |
241 | #else | |
242 | for (i = 0; ; i++) { | |
243 | rte_pipeline_run(p); | |
244 | ||
245 | if ((i & APP_FLUSH) == 0) | |
246 | rte_pipeline_flush(p); | |
247 | } | |
248 | #endif | |
249 | } |