4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <rte_malloc.h>
40 #include <rte_ethdev.h>
41 #include <rte_ether.h>
43 #include <rte_byteorder.h>
45 #include <rte_port_ring.h>
46 #include <rte_table_acl.h>
47 #include <rte_pipeline.h>
51 struct app_core_firewall_message_handle_params {
52 struct rte_ring *ring_req;
53 struct rte_ring *ring_resp;
55 struct rte_pipeline *p;
56 uint32_t *port_out_id;
61 app_message_handle(struct app_core_firewall_message_handle_params *params);
72 struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = {
74 .type = RTE_ACL_FIELD_TYPE_BITMASK,
75 .size = sizeof(uint8_t),
76 .field_index = PROTO_FIELD_IPV4,
77 .input_index = PROTO_FIELD_IPV4,
78 .offset = sizeof(struct ether_hdr) +
79 offsetof(struct ipv4_hdr, next_proto_id),
82 .type = RTE_ACL_FIELD_TYPE_MASK,
83 .size = sizeof(uint32_t),
84 .field_index = SRC_FIELD_IPV4,
85 .input_index = SRC_FIELD_IPV4,
86 .offset = sizeof(struct ether_hdr) +
87 offsetof(struct ipv4_hdr, src_addr),
90 .type = RTE_ACL_FIELD_TYPE_MASK,
91 .size = sizeof(uint32_t),
92 .field_index = DST_FIELD_IPV4,
93 .input_index = DST_FIELD_IPV4,
94 .offset = sizeof(struct ether_hdr) +
95 offsetof(struct ipv4_hdr, dst_addr),
98 .type = RTE_ACL_FIELD_TYPE_RANGE,
99 .size = sizeof(uint16_t),
100 .field_index = SRCP_FIELD_IPV4,
101 .input_index = SRCP_FIELD_IPV4,
102 .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr),
105 .type = RTE_ACL_FIELD_TYPE_RANGE,
106 .size = sizeof(uint16_t),
107 .field_index = DSTP_FIELD_IPV4,
108 .input_index = SRCP_FIELD_IPV4,
109 .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) +
115 app_main_loop_pipeline_firewall(void) {
116 struct rte_pipeline_params pipeline_params = {
118 .socket_id = rte_socket_id(),
121 struct rte_pipeline *p;
122 uint32_t port_in_id[APP_MAX_PORTS];
123 uint32_t port_out_id[APP_MAX_PORTS];
127 uint32_t core_id = rte_lcore_id();
128 struct app_core_params *core_params = app_get_core_params(core_id);
129 struct app_core_firewall_message_handle_params mh_params;
131 if ((core_params == NULL) || (core_params->core_type != APP_CORE_FW))
132 rte_panic("Core %u misconfiguration\n", core_id);
134 RTE_LOG(INFO, USER1, "Core %u is doing firewall\n", core_id);
136 /* Pipeline configuration */
137 p = rte_pipeline_create(&pipeline_params);
139 rte_panic("Unable to configure the pipeline\n");
141 /* Input port configuration */
142 for (i = 0; i < app.n_ports; i++) {
143 struct rte_port_ring_reader_params port_ring_params = {
144 .ring = app.rings[core_params->swq_in[i]],
147 struct rte_pipeline_port_in_params port_params = {
148 .ops = &rte_port_ring_reader_ops,
149 .arg_create = (void *) &port_ring_params,
152 .burst_size = app.bsz_swq_rd,
155 if (rte_pipeline_port_in_create(p, &port_params,
157 rte_panic("Unable to configure input port for "
161 /* Output port configuration */
162 for (i = 0; i < app.n_ports; i++) {
163 struct rte_port_ring_writer_params port_ring_params = {
164 .ring = app.rings[core_params->swq_out[i]],
165 .tx_burst_sz = app.bsz_swq_wr,
168 struct rte_pipeline_port_out_params port_params = {
169 .ops = &rte_port_ring_writer_ops,
170 .arg_create = (void *) &port_ring_params,
172 .f_action_bulk = NULL,
176 if (rte_pipeline_port_out_create(p, &port_params,
178 rte_panic("Unable to configure output port for "
182 /* Table configuration */
184 struct rte_table_acl_params table_acl_params = {
185 .name = "test", /* unique identifier for acl contexts */
186 .n_rules = app.max_firewall_rules,
187 .n_rule_fields = DIM(ipv4_field_formats),
190 struct rte_pipeline_table_params table_params = {
191 .ops = &rte_table_acl_ops,
192 .arg_create = &table_acl_params,
193 .f_action_hit = NULL,
194 .f_action_miss = NULL,
196 .action_data_size = 0,
199 memcpy(table_acl_params.field_format, ipv4_field_formats,
200 sizeof(ipv4_field_formats));
202 if (rte_pipeline_table_create(p, &table_params, &table_id))
203 rte_panic("Unable to configure the ACL table\n");
206 /* Interconnecting ports and tables */
207 for (i = 0; i < app.n_ports; i++)
208 if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
210 rte_panic("Unable to connect input port %u to "
211 "table %u\n", port_in_id[i], table_id);
213 /* Enable input ports */
214 for (i = 0; i < app.n_ports; i++)
215 if (rte_pipeline_port_in_enable(p, port_in_id[i]))
216 rte_panic("Unable to enable input port %u\n",
219 /* Check pipeline consistency */
220 if (rte_pipeline_check(p) < 0)
221 rte_panic("Pipeline consistency check failed\n");
223 /* Message handling */
224 mh_params.ring_req = app_get_ring_req(
225 app_get_first_core_id(APP_CORE_FW));
226 mh_params.ring_resp = app_get_ring_resp(
227 app_get_first_core_id(APP_CORE_FW));
229 mh_params.port_out_id = port_out_id;
230 mh_params.table_id = table_id;
236 if ((i & APP_FLUSH) == 0) {
237 rte_pipeline_flush(p);
238 app_message_handle(&mh_params);
244 app_message_handle(struct app_core_firewall_message_handle_params *params)
246 struct rte_ring *ring_req = params->ring_req;
247 struct rte_ring *ring_resp;
248 struct rte_mbuf *msg;
249 struct app_msg_req *req;
250 struct app_msg_resp *resp;
251 struct rte_pipeline *p;
252 uint32_t *port_out_id;
256 /* Read request message */
257 result = rte_ring_sc_dequeue(ring_req, (void **) &msg);
261 ring_resp = params->ring_resp;
263 port_out_id = params->port_out_id;
264 table_id = params->table_id;
267 req = (struct app_msg_req *) msg->ctrl.data;
269 case APP_MSG_REQ_PING:
275 case APP_MSG_REQ_FW_ADD:
277 struct rte_pipeline_table_entry entry = {
278 .action = RTE_PIPELINE_ACTION_PORT,
279 {.port_id = port_out_id[req->firewall_add.port]},
282 struct rte_pipeline_table_entry *entry_ptr;
286 result = rte_pipeline_table_entry_add(p, table_id,
287 &req->firewall_add.add_params, &entry, &key_found,
292 case APP_MSG_REQ_FW_DEL:
296 result = rte_pipeline_table_entry_delete(p, table_id,
297 &req->firewall_del.delete_params, &key_found, NULL);
302 rte_panic("FW unrecognized message type (%u)\n", req->type);
305 /* Fill in response message */
306 resp = (struct app_msg_resp *) msg->ctrl.data;
307 resp->result = result;
311 result = rte_ring_sp_enqueue(ring_resp, (void *) msg);
312 } while (result == -ENOBUFS);