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