1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson * Copyright(c) 2010-2014 Intel Corporation
3a9de470cSBruce Richardson */
4a9de470cSBruce Richardson
53c60274cSJie Zhou #ifndef RTE_EXEC_ENV_WINDOWS
63c60274cSJie Zhou
7fd1a85cbSDavid Marchand #include <rte_ip.h>
86723c0fcSBruce Richardson #include <rte_string_fns.h>
9a9de470cSBruce Richardson #include <rte_hexdump.h>
10a9de470cSBruce Richardson #include "test_table.h"
11a9de470cSBruce Richardson #include "test_table_acl.h"
12a9de470cSBruce Richardson
13a9de470cSBruce Richardson /*
14a9de470cSBruce Richardson * Rule and trace formats definitions.
15a9de470cSBruce Richardson **/
16a9de470cSBruce Richardson
17a9de470cSBruce Richardson struct ipv4_5tuple {
18a9de470cSBruce Richardson uint8_t proto;
19a9de470cSBruce Richardson uint32_t ip_src;
20a9de470cSBruce Richardson uint32_t ip_dst;
21a9de470cSBruce Richardson uint16_t port_src;
22a9de470cSBruce Richardson uint16_t port_dst;
23a9de470cSBruce Richardson };
24a9de470cSBruce Richardson
25a9de470cSBruce Richardson enum {
26a9de470cSBruce Richardson PROTO_FIELD_IPV4,
27a9de470cSBruce Richardson SRC_FIELD_IPV4,
28a9de470cSBruce Richardson DST_FIELD_IPV4,
29a9de470cSBruce Richardson SRCP_FIELD_IPV4,
30a9de470cSBruce Richardson DSTP_FIELD_IPV4,
31a9de470cSBruce Richardson NUM_FIELDS_IPV4
32a9de470cSBruce Richardson };
33a9de470cSBruce Richardson
34a9de470cSBruce Richardson struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
35a9de470cSBruce Richardson {
36a9de470cSBruce Richardson .type = RTE_ACL_FIELD_TYPE_BITMASK,
37a9de470cSBruce Richardson .size = sizeof(uint8_t),
38a9de470cSBruce Richardson .field_index = PROTO_FIELD_IPV4,
39a9de470cSBruce Richardson .input_index = PROTO_FIELD_IPV4,
40a9de470cSBruce Richardson .offset = offsetof(struct ipv4_5tuple, proto),
41a9de470cSBruce Richardson },
42a9de470cSBruce Richardson {
43a9de470cSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK,
44a9de470cSBruce Richardson .size = sizeof(uint32_t),
45a9de470cSBruce Richardson .field_index = SRC_FIELD_IPV4,
46a9de470cSBruce Richardson .input_index = SRC_FIELD_IPV4,
47a9de470cSBruce Richardson .offset = offsetof(struct ipv4_5tuple, ip_src),
48a9de470cSBruce Richardson },
49a9de470cSBruce Richardson {
50a9de470cSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK,
51a9de470cSBruce Richardson .size = sizeof(uint32_t),
52a9de470cSBruce Richardson .field_index = DST_FIELD_IPV4,
53a9de470cSBruce Richardson .input_index = DST_FIELD_IPV4,
54a9de470cSBruce Richardson .offset = offsetof(struct ipv4_5tuple, ip_dst),
55a9de470cSBruce Richardson },
56a9de470cSBruce Richardson {
57a9de470cSBruce Richardson .type = RTE_ACL_FIELD_TYPE_RANGE,
58a9de470cSBruce Richardson .size = sizeof(uint16_t),
59a9de470cSBruce Richardson .field_index = SRCP_FIELD_IPV4,
60a9de470cSBruce Richardson .input_index = SRCP_FIELD_IPV4,
61a9de470cSBruce Richardson .offset = offsetof(struct ipv4_5tuple, port_src),
62a9de470cSBruce Richardson },
63a9de470cSBruce Richardson {
64a9de470cSBruce Richardson .type = RTE_ACL_FIELD_TYPE_RANGE,
65a9de470cSBruce Richardson .size = sizeof(uint16_t),
66a9de470cSBruce Richardson .field_index = DSTP_FIELD_IPV4,
67a9de470cSBruce Richardson .input_index = SRCP_FIELD_IPV4,
68a9de470cSBruce Richardson .offset = offsetof(struct ipv4_5tuple, port_dst),
69a9de470cSBruce Richardson },
70a9de470cSBruce Richardson };
71a9de470cSBruce Richardson
72a9de470cSBruce Richardson struct rte_table_acl_rule_add_params table_acl_IPv4_rule;
73a9de470cSBruce Richardson
74a9de470cSBruce Richardson typedef int (*parse_5tuple)(char *text,
75a9de470cSBruce Richardson struct rte_table_acl_rule_add_params *rule);
76a9de470cSBruce Richardson
77a9de470cSBruce Richardson /*
78a9de470cSBruce Richardson * The order of the fields in the rule string after the initial '@'
79a9de470cSBruce Richardson */
80a9de470cSBruce Richardson enum {
81a9de470cSBruce Richardson CB_FLD_SRC_ADDR,
82a9de470cSBruce Richardson CB_FLD_DST_ADDR,
83a9de470cSBruce Richardson CB_FLD_SRC_PORT_RANGE,
84a9de470cSBruce Richardson CB_FLD_DST_PORT_RANGE,
85a9de470cSBruce Richardson CB_FLD_PROTO,
86a9de470cSBruce Richardson CB_FLD_NUM,
87a9de470cSBruce Richardson };
88a9de470cSBruce Richardson
89a9de470cSBruce Richardson
90a9de470cSBruce Richardson #define GET_CB_FIELD(in, fd, base, lim, dlm) \
91a9de470cSBruce Richardson do { \
92a9de470cSBruce Richardson unsigned long val; \
93a9de470cSBruce Richardson char *end; \
94a9de470cSBruce Richardson \
95a9de470cSBruce Richardson errno = 0; \
96a9de470cSBruce Richardson val = strtoul((in), &end, (base)); \
97a9de470cSBruce Richardson if (errno != 0 || end[0] != (dlm) || val > (lim)) \
98a9de470cSBruce Richardson return -EINVAL; \
99a9de470cSBruce Richardson (fd) = (typeof(fd)) val; \
100a9de470cSBruce Richardson (in) = end + 1; \
101a9de470cSBruce Richardson } while (0)
102a9de470cSBruce Richardson
103a9de470cSBruce Richardson
104a9de470cSBruce Richardson
105a9de470cSBruce Richardson
106a9de470cSBruce Richardson static int
parse_ipv4_net(const char * in,uint32_t * addr,uint32_t * mask_len)107a9de470cSBruce Richardson parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)
108a9de470cSBruce Richardson {
109a9de470cSBruce Richardson uint8_t a, b, c, d, m;
110a9de470cSBruce Richardson
111a9de470cSBruce Richardson GET_CB_FIELD(in, a, 0, UINT8_MAX, '.');
112a9de470cSBruce Richardson GET_CB_FIELD(in, b, 0, UINT8_MAX, '.');
113a9de470cSBruce Richardson GET_CB_FIELD(in, c, 0, UINT8_MAX, '.');
114a9de470cSBruce Richardson GET_CB_FIELD(in, d, 0, UINT8_MAX, '/');
115a9de470cSBruce Richardson GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
116a9de470cSBruce Richardson
1170c9da755SDavid Marchand addr[0] = RTE_IPV4(a, b, c, d);
118a9de470cSBruce Richardson mask_len[0] = m;
119a9de470cSBruce Richardson
120a9de470cSBruce Richardson return 0;
121a9de470cSBruce Richardson }
122a9de470cSBruce Richardson
123a9de470cSBruce Richardson static int
parse_port_range(const char * in,uint16_t * port_low,uint16_t * port_high)124a9de470cSBruce Richardson parse_port_range(const char *in, uint16_t *port_low, uint16_t *port_high)
125a9de470cSBruce Richardson {
126a9de470cSBruce Richardson uint16_t a, b;
127a9de470cSBruce Richardson
128a9de470cSBruce Richardson GET_CB_FIELD(in, a, 0, UINT16_MAX, ':');
129a9de470cSBruce Richardson GET_CB_FIELD(in, b, 0, UINT16_MAX, 0);
130a9de470cSBruce Richardson
131a9de470cSBruce Richardson port_low[0] = a;
132a9de470cSBruce Richardson port_high[0] = b;
133a9de470cSBruce Richardson
134a9de470cSBruce Richardson return 0;
135a9de470cSBruce Richardson }
136a9de470cSBruce Richardson
137a9de470cSBruce Richardson static int
parse_cb_ipv4_rule(char * str,struct rte_table_acl_rule_add_params * v)138a9de470cSBruce Richardson parse_cb_ipv4_rule(char *str, struct rte_table_acl_rule_add_params *v)
139a9de470cSBruce Richardson {
140a9de470cSBruce Richardson int i, rc;
141a9de470cSBruce Richardson char *s, *sp, *in[CB_FLD_NUM];
142a9de470cSBruce Richardson static const char *dlm = " \t\n";
143a9de470cSBruce Richardson
144a9de470cSBruce Richardson /*
145a9de470cSBruce Richardson ** Skip leading '@'
146a9de470cSBruce Richardson */
147a9de470cSBruce Richardson if (strchr(str, '@') != str)
148a9de470cSBruce Richardson return -EINVAL;
149a9de470cSBruce Richardson
150a9de470cSBruce Richardson s = str + 1;
151a9de470cSBruce Richardson
152a9de470cSBruce Richardson /*
153a9de470cSBruce Richardson * Populate the 'in' array with the location of each
154a9de470cSBruce Richardson * field in the string we're parsing
155a9de470cSBruce Richardson */
156a9de470cSBruce Richardson for (i = 0; i != DIM(in); i++) {
157a9de470cSBruce Richardson in[i] = strtok_r(s, dlm, &sp);
158a9de470cSBruce Richardson if (in[i] == NULL)
159a9de470cSBruce Richardson return -EINVAL;
160a9de470cSBruce Richardson s = NULL;
161a9de470cSBruce Richardson }
162a9de470cSBruce Richardson
163a9de470cSBruce Richardson /* Parse x.x.x.x/x */
164a9de470cSBruce Richardson rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
165a9de470cSBruce Richardson &v->field_value[SRC_FIELD_IPV4].value.u32,
166a9de470cSBruce Richardson &v->field_value[SRC_FIELD_IPV4].mask_range.u32);
167a9de470cSBruce Richardson if (rc != 0) {
168*f541aa2dSStephen Hemminger fprintf(stderr, "failed to read src address/mask: %s\n",
169a9de470cSBruce Richardson in[CB_FLD_SRC_ADDR]);
170a9de470cSBruce Richardson return rc;
171a9de470cSBruce Richardson }
172a9de470cSBruce Richardson
173a9de470cSBruce Richardson printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
174a9de470cSBruce Richardson v->field_value[SRC_FIELD_IPV4].mask_range.u32);
175a9de470cSBruce Richardson
176a9de470cSBruce Richardson /* Parse x.x.x.x/x */
177a9de470cSBruce Richardson rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
178a9de470cSBruce Richardson &v->field_value[DST_FIELD_IPV4].value.u32,
179a9de470cSBruce Richardson &v->field_value[DST_FIELD_IPV4].mask_range.u32);
180a9de470cSBruce Richardson if (rc != 0) {
181*f541aa2dSStephen Hemminger fprintf(stderr, "failed to read dest address/mask: %s\n",
182a9de470cSBruce Richardson in[CB_FLD_DST_ADDR]);
183a9de470cSBruce Richardson return rc;
184a9de470cSBruce Richardson }
185a9de470cSBruce Richardson
186a9de470cSBruce Richardson printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
187a9de470cSBruce Richardson v->field_value[DST_FIELD_IPV4].mask_range.u32);
188a9de470cSBruce Richardson /* Parse n:n */
189a9de470cSBruce Richardson rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
190a9de470cSBruce Richardson &v->field_value[SRCP_FIELD_IPV4].value.u16,
191a9de470cSBruce Richardson &v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
192a9de470cSBruce Richardson if (rc != 0) {
193*f541aa2dSStephen Hemminger fprintf(stderr, "failed to read source port range: %s\n",
194a9de470cSBruce Richardson in[CB_FLD_SRC_PORT_RANGE]);
195a9de470cSBruce Richardson return rc;
196a9de470cSBruce Richardson }
197a9de470cSBruce Richardson
198a9de470cSBruce Richardson printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
199a9de470cSBruce Richardson v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
200a9de470cSBruce Richardson /* Parse n:n */
201a9de470cSBruce Richardson rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
202a9de470cSBruce Richardson &v->field_value[DSTP_FIELD_IPV4].value.u16,
203a9de470cSBruce Richardson &v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
204a9de470cSBruce Richardson if (rc != 0) {
205*f541aa2dSStephen Hemminger fprintf(stderr, "failed to read dest port range: %s\n",
206a9de470cSBruce Richardson in[CB_FLD_DST_PORT_RANGE]);
207a9de470cSBruce Richardson return rc;
208a9de470cSBruce Richardson }
209a9de470cSBruce Richardson
210a9de470cSBruce Richardson printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
211a9de470cSBruce Richardson v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
212a9de470cSBruce Richardson /* parse 0/0xnn */
213a9de470cSBruce Richardson GET_CB_FIELD(in[CB_FLD_PROTO],
214a9de470cSBruce Richardson v->field_value[PROTO_FIELD_IPV4].value.u8,
215a9de470cSBruce Richardson 0, UINT8_MAX, '/');
216a9de470cSBruce Richardson GET_CB_FIELD(in[CB_FLD_PROTO],
217a9de470cSBruce Richardson v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
218a9de470cSBruce Richardson 0, UINT8_MAX, 0);
219a9de470cSBruce Richardson
220a9de470cSBruce Richardson printf("V=%u, mask=%u\n",
221a9de470cSBruce Richardson (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
222a9de470cSBruce Richardson v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
223a9de470cSBruce Richardson return 0;
224a9de470cSBruce Richardson }
225a9de470cSBruce Richardson
226a9de470cSBruce Richardson static int
parse_cb_ipv4_rule_del(char * str,struct rte_table_acl_rule_delete_params * v)227a9de470cSBruce Richardson parse_cb_ipv4_rule_del(char *str, struct rte_table_acl_rule_delete_params *v)
228a9de470cSBruce Richardson {
229a9de470cSBruce Richardson int i, rc;
230a9de470cSBruce Richardson char *s, *sp, *in[CB_FLD_NUM];
231a9de470cSBruce Richardson static const char *dlm = " \t\n";
232a9de470cSBruce Richardson
233a9de470cSBruce Richardson /*
234a9de470cSBruce Richardson ** Skip leading '@'
235a9de470cSBruce Richardson */
236a9de470cSBruce Richardson if (strchr(str, '@') != str)
237a9de470cSBruce Richardson return -EINVAL;
238a9de470cSBruce Richardson
239a9de470cSBruce Richardson s = str + 1;
240a9de470cSBruce Richardson
241a9de470cSBruce Richardson /*
242a9de470cSBruce Richardson * Populate the 'in' array with the location of each
243a9de470cSBruce Richardson * field in the string we're parsing
244a9de470cSBruce Richardson */
245a9de470cSBruce Richardson for (i = 0; i != DIM(in); i++) {
246a9de470cSBruce Richardson in[i] = strtok_r(s, dlm, &sp);
247a9de470cSBruce Richardson if (in[i] == NULL)
248a9de470cSBruce Richardson return -EINVAL;
249a9de470cSBruce Richardson s = NULL;
250a9de470cSBruce Richardson }
251a9de470cSBruce Richardson
252a9de470cSBruce Richardson /* Parse x.x.x.x/x */
253a9de470cSBruce Richardson rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
254a9de470cSBruce Richardson &v->field_value[SRC_FIELD_IPV4].value.u32,
255a9de470cSBruce Richardson &v->field_value[SRC_FIELD_IPV4].mask_range.u32);
256a9de470cSBruce Richardson if (rc != 0) {
257*f541aa2dSStephen Hemminger fprintf(stderr, "failed to read src address/mask: %s\n",
258a9de470cSBruce Richardson in[CB_FLD_SRC_ADDR]);
259a9de470cSBruce Richardson return rc;
260a9de470cSBruce Richardson }
261a9de470cSBruce Richardson
262a9de470cSBruce Richardson printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
263a9de470cSBruce Richardson v->field_value[SRC_FIELD_IPV4].mask_range.u32);
264a9de470cSBruce Richardson
265a9de470cSBruce Richardson /* Parse x.x.x.x/x */
266a9de470cSBruce Richardson rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
267a9de470cSBruce Richardson &v->field_value[DST_FIELD_IPV4].value.u32,
268a9de470cSBruce Richardson &v->field_value[DST_FIELD_IPV4].mask_range.u32);
269a9de470cSBruce Richardson if (rc != 0) {
270*f541aa2dSStephen Hemminger fprintf(stderr, "failed to read dest address/mask: %s\n",
271a9de470cSBruce Richardson in[CB_FLD_DST_ADDR]);
272a9de470cSBruce Richardson return rc;
273a9de470cSBruce Richardson }
274a9de470cSBruce Richardson
275a9de470cSBruce Richardson printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
276a9de470cSBruce Richardson v->field_value[DST_FIELD_IPV4].mask_range.u32);
277a9de470cSBruce Richardson /* Parse n:n */
278a9de470cSBruce Richardson rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
279a9de470cSBruce Richardson &v->field_value[SRCP_FIELD_IPV4].value.u16,
280a9de470cSBruce Richardson &v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
281a9de470cSBruce Richardson if (rc != 0) {
282*f541aa2dSStephen Hemminger fprintf(stderr, "failed to read source port range: %s\n",
283a9de470cSBruce Richardson in[CB_FLD_SRC_PORT_RANGE]);
284a9de470cSBruce Richardson return rc;
285a9de470cSBruce Richardson }
286a9de470cSBruce Richardson
287a9de470cSBruce Richardson printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
288a9de470cSBruce Richardson v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
289a9de470cSBruce Richardson /* Parse n:n */
290a9de470cSBruce Richardson rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
291a9de470cSBruce Richardson &v->field_value[DSTP_FIELD_IPV4].value.u16,
292a9de470cSBruce Richardson &v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
293a9de470cSBruce Richardson if (rc != 0) {
294*f541aa2dSStephen Hemminger fprintf(stderr, "failed to read dest port range: %s\n",
295a9de470cSBruce Richardson in[CB_FLD_DST_PORT_RANGE]);
296a9de470cSBruce Richardson return rc;
297a9de470cSBruce Richardson }
298a9de470cSBruce Richardson
299a9de470cSBruce Richardson printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
300a9de470cSBruce Richardson v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
301a9de470cSBruce Richardson /* parse 0/0xnn */
302a9de470cSBruce Richardson GET_CB_FIELD(in[CB_FLD_PROTO],
303a9de470cSBruce Richardson v->field_value[PROTO_FIELD_IPV4].value.u8,
304a9de470cSBruce Richardson 0, UINT8_MAX, '/');
305a9de470cSBruce Richardson GET_CB_FIELD(in[CB_FLD_PROTO],
306a9de470cSBruce Richardson v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
307a9de470cSBruce Richardson 0, UINT8_MAX, 0);
308a9de470cSBruce Richardson
309a9de470cSBruce Richardson printf("V=%u, mask=%u\n",
310a9de470cSBruce Richardson (unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
311a9de470cSBruce Richardson v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
312a9de470cSBruce Richardson return 0;
313a9de470cSBruce Richardson }
314a9de470cSBruce Richardson
315a9de470cSBruce Richardson /*
316a9de470cSBruce Richardson * The format for these rules DO NOT need the port ranges to be
317a9de470cSBruce Richardson * separated by ' : ', just ':'. It's a lot more readable and
318a9de470cSBruce Richardson * cleaner, IMO.
319a9de470cSBruce Richardson */
320a9de470cSBruce Richardson char lines[][128] = {
321a9de470cSBruce Richardson "@0.0.0.0/0 0.0.0.0/0 0:65535 0:65535 2/0xff", /* Protocol check */
322a9de470cSBruce Richardson "@192.168.3.1/32 0.0.0.0/0 0:65535 0:65535 0/0", /* Src IP checl */
323a9de470cSBruce Richardson "@0.0.0.0/0 10.4.4.1/32 0:65535 0:65535 0/0", /* dst IP check */
324a9de470cSBruce Richardson "@0.0.0.0/0 0.0.0.0/0 105:105 0:65535 0/0", /* src port check */
325a9de470cSBruce Richardson "@0.0.0.0/0 0.0.0.0/0 0:65535 206:206 0/0", /* dst port check */
326a9de470cSBruce Richardson };
327a9de470cSBruce Richardson
328a9de470cSBruce Richardson char line[128];
329a9de470cSBruce Richardson
330a9de470cSBruce Richardson
331a9de470cSBruce Richardson static int
setup_acl_pipeline(void)332a9de470cSBruce Richardson setup_acl_pipeline(void)
333a9de470cSBruce Richardson {
334a9de470cSBruce Richardson int ret;
335a9de470cSBruce Richardson int i;
336a9de470cSBruce Richardson struct rte_pipeline_params pipeline_params = {
337a9de470cSBruce Richardson .name = "PIPELINE",
338a9de470cSBruce Richardson .socket_id = 0,
339a9de470cSBruce Richardson };
340a9de470cSBruce Richardson uint32_t n;
341a9de470cSBruce Richardson struct rte_table_acl_rule_add_params rule_params;
342a9de470cSBruce Richardson struct rte_pipeline_table_acl_rule_delete_params *delete_params;
343a9de470cSBruce Richardson parse_5tuple parser;
344a9de470cSBruce Richardson char acl_name[64];
345a9de470cSBruce Richardson
346a9de470cSBruce Richardson /* Pipeline configuration */
347a9de470cSBruce Richardson p = rte_pipeline_create(&pipeline_params);
348a9de470cSBruce Richardson if (p == NULL) {
349*f541aa2dSStephen Hemminger fprintf(stderr, "%s: Failed to configure pipeline\n",
350a9de470cSBruce Richardson __func__);
351a9de470cSBruce Richardson goto fail;
352a9de470cSBruce Richardson }
353a9de470cSBruce Richardson
354a9de470cSBruce Richardson /* Input port configuration */
355a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
356a9de470cSBruce Richardson struct rte_port_ring_reader_params port_ring_params = {
357a9de470cSBruce Richardson .ring = rings_rx[i],
358a9de470cSBruce Richardson };
359a9de470cSBruce Richardson
360a9de470cSBruce Richardson struct rte_pipeline_port_in_params port_params = {
361a9de470cSBruce Richardson .ops = &rte_port_ring_reader_ops,
362a9de470cSBruce Richardson .arg_create = (void *) &port_ring_params,
363a9de470cSBruce Richardson .f_action = NULL,
364a9de470cSBruce Richardson .burst_size = BURST_SIZE,
365a9de470cSBruce Richardson };
366a9de470cSBruce Richardson
367a9de470cSBruce Richardson /* Put in action for some ports */
368a9de470cSBruce Richardson if (i)
369a9de470cSBruce Richardson port_params.f_action = port_in_action;
370a9de470cSBruce Richardson
371a9de470cSBruce Richardson ret = rte_pipeline_port_in_create(p, &port_params,
372a9de470cSBruce Richardson &port_in_id[i]);
373a9de470cSBruce Richardson if (ret) {
374a9de470cSBruce Richardson rte_panic("Unable to configure input port %d, ret:%d\n",
375a9de470cSBruce Richardson i, ret);
376a9de470cSBruce Richardson goto fail;
377a9de470cSBruce Richardson }
378a9de470cSBruce Richardson }
379a9de470cSBruce Richardson
380a9de470cSBruce Richardson /* output Port configuration */
381a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
382a9de470cSBruce Richardson struct rte_port_ring_writer_params port_ring_params = {
383a9de470cSBruce Richardson .ring = rings_tx[i],
384a9de470cSBruce Richardson .tx_burst_sz = BURST_SIZE,
385a9de470cSBruce Richardson };
386a9de470cSBruce Richardson
387a9de470cSBruce Richardson struct rte_pipeline_port_out_params port_params = {
388a9de470cSBruce Richardson .ops = &rte_port_ring_writer_ops,
389a9de470cSBruce Richardson .arg_create = (void *) &port_ring_params,
390a9de470cSBruce Richardson .f_action = NULL,
391a9de470cSBruce Richardson .arg_ah = NULL,
392a9de470cSBruce Richardson };
393a9de470cSBruce Richardson
394a9de470cSBruce Richardson
395a9de470cSBruce Richardson if (rte_pipeline_port_out_create(p, &port_params,
396a9de470cSBruce Richardson &port_out_id[i])) {
397a9de470cSBruce Richardson rte_panic("Unable to configure output port %d\n", i);
398a9de470cSBruce Richardson goto fail;
399a9de470cSBruce Richardson }
400a9de470cSBruce Richardson }
401a9de470cSBruce Richardson
402a9de470cSBruce Richardson /* Table configuration */
403a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
404a9de470cSBruce Richardson struct rte_pipeline_table_params table_params;
405a9de470cSBruce Richardson
406a9de470cSBruce Richardson /* Set up defaults for stub */
407a9de470cSBruce Richardson table_params.ops = &rte_table_stub_ops;
408a9de470cSBruce Richardson table_params.arg_create = NULL;
409a9de470cSBruce Richardson table_params.f_action_hit = action_handler_hit;
410a9de470cSBruce Richardson table_params.f_action_miss = NULL;
411a9de470cSBruce Richardson table_params.action_data_size = 0;
412a9de470cSBruce Richardson
413*f541aa2dSStephen Hemminger printf("miss_action=%x\n",
414a9de470cSBruce Richardson table_entry_miss_action);
415a9de470cSBruce Richardson
416a9de470cSBruce Richardson printf("RTE_ACL_RULE_SZ(%zu) = %zu\n", DIM(ipv4_defs),
417a9de470cSBruce Richardson RTE_ACL_RULE_SZ(DIM(ipv4_defs)));
418a9de470cSBruce Richardson
419a9de470cSBruce Richardson struct rte_table_acl_params acl_params;
420a9de470cSBruce Richardson
421a9de470cSBruce Richardson acl_params.n_rules = 1 << 5;
422a9de470cSBruce Richardson acl_params.n_rule_fields = DIM(ipv4_defs);
423a9de470cSBruce Richardson snprintf(acl_name, sizeof(acl_name), "ACL%d", i);
424a9de470cSBruce Richardson acl_params.name = acl_name;
425a9de470cSBruce Richardson memcpy(acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
426a9de470cSBruce Richardson
427a9de470cSBruce Richardson table_params.ops = &rte_table_acl_ops;
428a9de470cSBruce Richardson table_params.arg_create = &acl_params;
429a9de470cSBruce Richardson
430a9de470cSBruce Richardson if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
431a9de470cSBruce Richardson rte_panic("Unable to configure table %u\n", i);
432a9de470cSBruce Richardson goto fail;
433a9de470cSBruce Richardson }
434a9de470cSBruce Richardson
435a9de470cSBruce Richardson if (connect_miss_action_to_table) {
436a9de470cSBruce Richardson if (rte_pipeline_table_create(p, &table_params,
437a9de470cSBruce Richardson &table_id[i+2])) {
438a9de470cSBruce Richardson rte_panic("Unable to configure table %u\n", i);
439a9de470cSBruce Richardson goto fail;
440a9de470cSBruce Richardson }
441a9de470cSBruce Richardson }
442a9de470cSBruce Richardson }
443a9de470cSBruce Richardson
444a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
445a9de470cSBruce Richardson if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
446a9de470cSBruce Richardson table_id[i])) {
447a9de470cSBruce Richardson rte_panic("Unable to connect input port %u to "
448a9de470cSBruce Richardson "table %u\n",
449a9de470cSBruce Richardson port_in_id[i], table_id[i]);
450a9de470cSBruce Richardson goto fail;
451a9de470cSBruce Richardson }
452a9de470cSBruce Richardson }
453a9de470cSBruce Richardson
454a9de470cSBruce Richardson /* Add bulk entries to tables */
455a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
456a9de470cSBruce Richardson struct rte_table_acl_rule_add_params keys[5];
457a9de470cSBruce Richardson struct rte_pipeline_table_entry entries[5];
458a9de470cSBruce Richardson struct rte_table_acl_rule_add_params *key_array[5];
459a9de470cSBruce Richardson struct rte_pipeline_table_entry *table_entries[5];
460a9de470cSBruce Richardson int key_found[5];
461a9de470cSBruce Richardson struct rte_pipeline_table_entry *table_entries_ptr[5];
462a9de470cSBruce Richardson struct rte_pipeline_table_entry entries_ptr[5];
463a9de470cSBruce Richardson
464a9de470cSBruce Richardson parser = parse_cb_ipv4_rule;
465a9de470cSBruce Richardson for (n = 0; n < 5; n++) {
466a9de470cSBruce Richardson memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_add_params));
467a9de470cSBruce Richardson key_array[n] = &keys[n];
468a9de470cSBruce Richardson
4696723c0fcSBruce Richardson strlcpy(line, lines[n], sizeof(line));
470a9de470cSBruce Richardson printf("PARSING [%s]\n", line);
471a9de470cSBruce Richardson
472a9de470cSBruce Richardson ret = parser(line, &keys[n]);
473a9de470cSBruce Richardson if (ret != 0) {
474*f541aa2dSStephen Hemminger fprintf(stderr,
475*f541aa2dSStephen Hemminger "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
476a9de470cSBruce Richardson n, ret, strerror(-ret));
477a9de470cSBruce Richardson return ret;
478a9de470cSBruce Richardson }
479a9de470cSBruce Richardson
480a9de470cSBruce Richardson keys[n].priority = RTE_ACL_MAX_PRIORITY - n - 1;
481a9de470cSBruce Richardson
482a9de470cSBruce Richardson entries[n].action = RTE_PIPELINE_ACTION_PORT;
483a9de470cSBruce Richardson entries[n].port_id = port_out_id[i^1];
484a9de470cSBruce Richardson table_entries[n] = &entries[n];
485a9de470cSBruce Richardson table_entries_ptr[n] = &entries_ptr[n];
486a9de470cSBruce Richardson }
487a9de470cSBruce Richardson
488a9de470cSBruce Richardson ret = rte_pipeline_table_entry_add_bulk(p, table_id[i],
489a9de470cSBruce Richardson (void **)key_array, table_entries, 5, key_found, table_entries_ptr);
490a9de470cSBruce Richardson if (ret < 0) {
491a9de470cSBruce Richardson rte_panic("Add entry bulk to table %u failed (%d)\n",
492a9de470cSBruce Richardson table_id[i], ret);
493a9de470cSBruce Richardson goto fail;
494a9de470cSBruce Richardson }
495a9de470cSBruce Richardson }
496a9de470cSBruce Richardson
497a9de470cSBruce Richardson /* Delete bulk entries from tables */
498a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
499a9de470cSBruce Richardson struct rte_table_acl_rule_delete_params keys[5];
500a9de470cSBruce Richardson struct rte_table_acl_rule_delete_params *key_array[5];
501a9de470cSBruce Richardson struct rte_pipeline_table_entry *table_entries[5];
502a9de470cSBruce Richardson int key_found[5];
503a9de470cSBruce Richardson
504a9de470cSBruce Richardson memset(table_entries, 0, sizeof(table_entries));
505a9de470cSBruce Richardson
506a9de470cSBruce Richardson for (n = 0; n < 5; n++) {
507a9de470cSBruce Richardson memset(&keys[n], 0, sizeof(struct rte_table_acl_rule_delete_params));
508a9de470cSBruce Richardson key_array[n] = &keys[n];
509a9de470cSBruce Richardson
5106723c0fcSBruce Richardson strlcpy(line, lines[n], sizeof(line));
511a9de470cSBruce Richardson printf("PARSING [%s]\n", line);
512a9de470cSBruce Richardson
513a9de470cSBruce Richardson ret = parse_cb_ipv4_rule_del(line, &keys[n]);
514a9de470cSBruce Richardson if (ret != 0) {
515*f541aa2dSStephen Hemminger fprintf(stderr,
516*f541aa2dSStephen Hemminger "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
517a9de470cSBruce Richardson n, ret, strerror(-ret));
518a9de470cSBruce Richardson return ret;
519a9de470cSBruce Richardson }
520a9de470cSBruce Richardson }
521a9de470cSBruce Richardson
522a9de470cSBruce Richardson ret = rte_pipeline_table_entry_delete_bulk(p, table_id[i],
523a9de470cSBruce Richardson (void **)key_array, 5, key_found, table_entries);
524a9de470cSBruce Richardson if (ret < 0) {
525a9de470cSBruce Richardson rte_panic("Delete bulk entries from table %u failed (%d)\n",
526a9de470cSBruce Richardson table_id[i], ret);
527a9de470cSBruce Richardson goto fail;
528a9de470cSBruce Richardson } else
529a9de470cSBruce Richardson printf("Bulk deleted rules.\n");
530a9de470cSBruce Richardson }
531a9de470cSBruce Richardson
532a9de470cSBruce Richardson /* Add entries to tables */
533a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
534a9de470cSBruce Richardson struct rte_pipeline_table_entry table_entry = {
535a9de470cSBruce Richardson .action = RTE_PIPELINE_ACTION_PORT,
536a9de470cSBruce Richardson {.port_id = port_out_id[i^1]},
537a9de470cSBruce Richardson };
538a9de470cSBruce Richardson int key_found;
539a9de470cSBruce Richardson struct rte_pipeline_table_entry *entry_ptr;
540a9de470cSBruce Richardson
541a9de470cSBruce Richardson memset(&rule_params, 0, sizeof(rule_params));
542a9de470cSBruce Richardson parser = parse_cb_ipv4_rule;
543a9de470cSBruce Richardson
544a9de470cSBruce Richardson for (n = 1; n <= 5; n++) {
5456723c0fcSBruce Richardson strlcpy(line, lines[n - 1], sizeof(line));
546a9de470cSBruce Richardson printf("PARSING [%s]\n", line);
547a9de470cSBruce Richardson
548a9de470cSBruce Richardson ret = parser(line, &rule_params);
549a9de470cSBruce Richardson if (ret != 0) {
550*f541aa2dSStephen Hemminger fprintf(stderr,
551*f541aa2dSStephen Hemminger "line %u: parse_cb_ipv4vlan_rule failed, error code: %d (%s)\n",
552a9de470cSBruce Richardson n, ret, strerror(-ret));
553a9de470cSBruce Richardson return ret;
554a9de470cSBruce Richardson }
555a9de470cSBruce Richardson
556a9de470cSBruce Richardson rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
557a9de470cSBruce Richardson
558a9de470cSBruce Richardson ret = rte_pipeline_table_entry_add(p, table_id[i],
559a9de470cSBruce Richardson &rule_params,
560a9de470cSBruce Richardson &table_entry, &key_found, &entry_ptr);
561a9de470cSBruce Richardson if (ret < 0) {
562a9de470cSBruce Richardson rte_panic("Add entry to table %u failed (%d)\n",
563a9de470cSBruce Richardson table_id[i], ret);
564a9de470cSBruce Richardson goto fail;
565a9de470cSBruce Richardson }
566a9de470cSBruce Richardson }
567a9de470cSBruce Richardson
568a9de470cSBruce Richardson /* delete a few rules */
569a9de470cSBruce Richardson for (n = 2; n <= 3; n++) {
5706723c0fcSBruce Richardson strlcpy(line, lines[n - 1], sizeof(line));
571a9de470cSBruce Richardson printf("PARSING [%s]\n", line);
572a9de470cSBruce Richardson
573a9de470cSBruce Richardson ret = parser(line, &rule_params);
574a9de470cSBruce Richardson if (ret != 0) {
575*f541aa2dSStephen Hemminger fprintf(stderr,
576*f541aa2dSStephen Hemminger "line %u: parse rule failed, error code: %d (%s)\n",
577a9de470cSBruce Richardson n, ret, strerror(-ret));
578a9de470cSBruce Richardson return ret;
579a9de470cSBruce Richardson }
580a9de470cSBruce Richardson
581a9de470cSBruce Richardson delete_params = (struct
582a9de470cSBruce Richardson rte_pipeline_table_acl_rule_delete_params *)
583a9de470cSBruce Richardson &(rule_params.field_value[0]);
584a9de470cSBruce Richardson ret = rte_pipeline_table_entry_delete(p, table_id[i],
585a9de470cSBruce Richardson delete_params, &key_found, NULL);
586a9de470cSBruce Richardson if (ret < 0) {
587a9de470cSBruce Richardson rte_panic("Add entry to table %u failed (%d)\n",
588a9de470cSBruce Richardson table_id[i], ret);
589a9de470cSBruce Richardson goto fail;
590a9de470cSBruce Richardson } else
591a9de470cSBruce Richardson printf("Deleted Rule.\n");
592a9de470cSBruce Richardson }
593a9de470cSBruce Richardson
594a9de470cSBruce Richardson
595a9de470cSBruce Richardson /* Try to add duplicates */
596a9de470cSBruce Richardson for (n = 1; n <= 5; n++) {
5976723c0fcSBruce Richardson strlcpy(line, lines[n - 1], sizeof(line));
598a9de470cSBruce Richardson printf("PARSING [%s]\n", line);
599a9de470cSBruce Richardson
600a9de470cSBruce Richardson ret = parser(line, &rule_params);
601a9de470cSBruce Richardson if (ret != 0) {
602*f541aa2dSStephen Hemminger fprintf(stderr,
603*f541aa2dSStephen Hemminger "line %u: parse rule failed, error code: %d (%s)\n",
604a9de470cSBruce Richardson n, ret, strerror(-ret));
605a9de470cSBruce Richardson return ret;
606a9de470cSBruce Richardson }
607a9de470cSBruce Richardson
608a9de470cSBruce Richardson rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
609a9de470cSBruce Richardson
610a9de470cSBruce Richardson ret = rte_pipeline_table_entry_add(p, table_id[i],
611a9de470cSBruce Richardson &rule_params,
612a9de470cSBruce Richardson &table_entry, &key_found, &entry_ptr);
613a9de470cSBruce Richardson if (ret < 0) {
614a9de470cSBruce Richardson rte_panic("Add entry to table %u failed (%d)\n",
615a9de470cSBruce Richardson table_id[i], ret);
616a9de470cSBruce Richardson goto fail;
617a9de470cSBruce Richardson }
618a9de470cSBruce Richardson }
619a9de470cSBruce Richardson }
620a9de470cSBruce Richardson
621a9de470cSBruce Richardson /* Enable input ports */
622a9de470cSBruce Richardson for (i = 0; i < N_PORTS ; i++)
623a9de470cSBruce Richardson if (rte_pipeline_port_in_enable(p, port_in_id[i]))
624a9de470cSBruce Richardson rte_panic("Unable to enable input port %u\n",
625a9de470cSBruce Richardson port_in_id[i]);
626a9de470cSBruce Richardson
627a9de470cSBruce Richardson /* Check pipeline consistency */
628a9de470cSBruce Richardson if (rte_pipeline_check(p) < 0) {
629a9de470cSBruce Richardson rte_panic("Pipeline consistency check failed\n");
630a9de470cSBruce Richardson goto fail;
631a9de470cSBruce Richardson }
632a9de470cSBruce Richardson
633a9de470cSBruce Richardson return 0;
634a9de470cSBruce Richardson fail:
635a9de470cSBruce Richardson
636a9de470cSBruce Richardson return -1;
637a9de470cSBruce Richardson }
638a9de470cSBruce Richardson
639a9de470cSBruce Richardson static int
test_pipeline_single_filter(int expected_count)640a9de470cSBruce Richardson test_pipeline_single_filter(int expected_count)
641a9de470cSBruce Richardson {
642a9de470cSBruce Richardson int i, j, ret, tx_count;
643a9de470cSBruce Richardson struct ipv4_5tuple five_tuple;
644a9de470cSBruce Richardson
645a9de470cSBruce Richardson /* Allocate a few mbufs and manually insert into the rings. */
646a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
647a9de470cSBruce Richardson for (j = 0; j < 8; j++) {
648a9de470cSBruce Richardson struct rte_mbuf *mbuf;
649a9de470cSBruce Richardson
650a9de470cSBruce Richardson mbuf = rte_pktmbuf_alloc(pool);
651a9de470cSBruce Richardson if (mbuf == NULL)
652a9de470cSBruce Richardson /* this will cause test failure after cleanup
653a9de470cSBruce Richardson * of already enqueued mbufs, as the mbuf
654a9de470cSBruce Richardson * counts won't match */
655a9de470cSBruce Richardson break;
656a9de470cSBruce Richardson memset(rte_pktmbuf_mtod(mbuf, char *), 0x00,
657a9de470cSBruce Richardson sizeof(struct ipv4_5tuple));
658a9de470cSBruce Richardson
659a9de470cSBruce Richardson five_tuple.proto = j;
6600c9da755SDavid Marchand five_tuple.ip_src = rte_bswap32(RTE_IPV4(192, 168, j, 1));
6610c9da755SDavid Marchand five_tuple.ip_dst = rte_bswap32(RTE_IPV4(10, 4, j, 1));
662a9de470cSBruce Richardson five_tuple.port_src = rte_bswap16(100 + j);
663a9de470cSBruce Richardson five_tuple.port_dst = rte_bswap16(200 + j);
664a9de470cSBruce Richardson
665a9de470cSBruce Richardson memcpy(rte_pktmbuf_mtod(mbuf, char *), &five_tuple,
666a9de470cSBruce Richardson sizeof(struct ipv4_5tuple));
667*f541aa2dSStephen Hemminger printf("%s: Enqueue onto ring %d\n",
668a9de470cSBruce Richardson __func__, i);
669a9de470cSBruce Richardson rte_ring_enqueue(rings_rx[i], mbuf);
670a9de470cSBruce Richardson }
671a9de470cSBruce Richardson }
672a9de470cSBruce Richardson
673a9de470cSBruce Richardson /* Run pipeline once */
674a9de470cSBruce Richardson for (i = 0; i< N_PORTS; i++)
675a9de470cSBruce Richardson rte_pipeline_run(p);
676a9de470cSBruce Richardson
677a9de470cSBruce Richardson rte_pipeline_flush(p);
678a9de470cSBruce Richardson
679a9de470cSBruce Richardson tx_count = 0;
680a9de470cSBruce Richardson
681a9de470cSBruce Richardson for (i = 0; i < N_PORTS; i++) {
682a9de470cSBruce Richardson void *objs[RING_TX_SIZE];
683a9de470cSBruce Richardson struct rte_mbuf *mbuf;
684a9de470cSBruce Richardson
685a9de470cSBruce Richardson ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10, NULL);
686a9de470cSBruce Richardson if (ret <= 0) {
687a9de470cSBruce Richardson printf("Got no objects from ring %d - error code %d\n",
688a9de470cSBruce Richardson i, ret);
689a9de470cSBruce Richardson } else {
690a9de470cSBruce Richardson printf("Got %d object(s) from ring %d!\n", ret, i);
691a9de470cSBruce Richardson for (j = 0; j < ret; j++) {
692a9de470cSBruce Richardson mbuf = objs[j];
693a9de470cSBruce Richardson rte_hexdump(stdout, "mbuf",
694a9de470cSBruce Richardson rte_pktmbuf_mtod(mbuf, char *), 64);
695a9de470cSBruce Richardson rte_pktmbuf_free(mbuf);
696a9de470cSBruce Richardson }
697a9de470cSBruce Richardson tx_count += ret;
698a9de470cSBruce Richardson }
699a9de470cSBruce Richardson }
700a9de470cSBruce Richardson
701a9de470cSBruce Richardson if (tx_count != expected_count) {
702*f541aa2dSStephen Hemminger fprintf(stderr,
703*f541aa2dSStephen Hemminger "%s: Unexpected packets for ACL test, expected %d, got %d\n",
704a9de470cSBruce Richardson __func__, expected_count, tx_count);
705a9de470cSBruce Richardson goto fail;
706a9de470cSBruce Richardson }
707a9de470cSBruce Richardson
708a9de470cSBruce Richardson rte_pipeline_free(p);
709a9de470cSBruce Richardson
710a9de470cSBruce Richardson return 0;
711a9de470cSBruce Richardson fail:
712a9de470cSBruce Richardson return -1;
713a9de470cSBruce Richardson
714a9de470cSBruce Richardson }
715a9de470cSBruce Richardson
716a9de470cSBruce Richardson int
test_table_acl(void)717a9de470cSBruce Richardson test_table_acl(void)
718a9de470cSBruce Richardson {
719a9de470cSBruce Richardson
720a9de470cSBruce Richardson
721a9de470cSBruce Richardson override_hit_mask = 0xFF; /* All packets are a hit */
722a9de470cSBruce Richardson
723a9de470cSBruce Richardson setup_acl_pipeline();
724a9de470cSBruce Richardson if (test_pipeline_single_filter(10) < 0)
725a9de470cSBruce Richardson return -1;
726a9de470cSBruce Richardson
727a9de470cSBruce Richardson return 0;
728a9de470cSBruce Richardson }
7293c60274cSJie Zhou
7303c60274cSJie Zhou #endif /* !RTE_EXEC_ENV_WINDOWS */
731