xref: /dpdk/examples/ipsec-secgw/sp6.c (revision 9ac91e2f7339e66658ef55b756a06b328e336fde)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
23998e2a0SBruce Richardson  * Copyright(c) 2016 Intel Corporation
3906257e9SSergio Gonzalez Monroy  */
4906257e9SSergio Gonzalez Monroy 
5906257e9SSergio Gonzalez Monroy /*
6906257e9SSergio Gonzalez Monroy  * Security Policies
7906257e9SSergio Gonzalez Monroy  */
8906257e9SSergio Gonzalez Monroy #include <sys/types.h>
9906257e9SSergio Gonzalez Monroy #include <netinet/in.h>
10906257e9SSergio Gonzalez Monroy #include <netinet/ip6.h>
11906257e9SSergio Gonzalez Monroy 
12906257e9SSergio Gonzalez Monroy #include <rte_acl.h>
13906257e9SSergio Gonzalez Monroy #include <rte_ip.h>
14906257e9SSergio Gonzalez Monroy 
15906257e9SSergio Gonzalez Monroy #include "ipsec.h"
160d547ed0SFan Zhang #include "parser.h"
17906257e9SSergio Gonzalez Monroy 
18b0806375SVladimir Medvedkin #define INIT_ACL_RULE_NUM	128
19906257e9SSergio Gonzalez Monroy 
20906257e9SSergio Gonzalez Monroy enum {
21906257e9SSergio Gonzalez Monroy 	IP6_PROTO,
22906257e9SSergio Gonzalez Monroy 	IP6_SRC0,
23906257e9SSergio Gonzalez Monroy 	IP6_SRC1,
24906257e9SSergio Gonzalez Monroy 	IP6_SRC2,
25906257e9SSergio Gonzalez Monroy 	IP6_SRC3,
26906257e9SSergio Gonzalez Monroy 	IP6_DST0,
27906257e9SSergio Gonzalez Monroy 	IP6_DST1,
28906257e9SSergio Gonzalez Monroy 	IP6_DST2,
29906257e9SSergio Gonzalez Monroy 	IP6_DST3,
30906257e9SSergio Gonzalez Monroy 	IP6_SRCP,
31906257e9SSergio Gonzalez Monroy 	IP6_DSTP,
32906257e9SSergio Gonzalez Monroy 	IP6_NUM
33906257e9SSergio Gonzalez Monroy };
34906257e9SSergio Gonzalez Monroy 
35d92fc70eSKonstantin Ananyev static struct rte_acl_field_def ip6_defs[IP6_NUM] = {
36906257e9SSergio Gonzalez Monroy 	{
37906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_BITMASK,
38906257e9SSergio Gonzalez Monroy 	.size = sizeof(uint8_t),
39906257e9SSergio Gonzalez Monroy 	.field_index = IP6_PROTO,
40906257e9SSergio Gonzalez Monroy 	.input_index = IP6_PROTO,
41906257e9SSergio Gonzalez Monroy 	.offset = 0,
42906257e9SSergio Gonzalez Monroy 	},
43906257e9SSergio Gonzalez Monroy 	{
44906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
45906257e9SSergio Gonzalez Monroy 	.size = 4,
46906257e9SSergio Gonzalez Monroy 	.field_index = IP6_SRC0,
47906257e9SSergio Gonzalez Monroy 	.input_index = IP6_SRC0,
48906257e9SSergio Gonzalez Monroy 	.offset = 2
49906257e9SSergio Gonzalez Monroy 	},
50906257e9SSergio Gonzalez Monroy 	{
51906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
52906257e9SSergio Gonzalez Monroy 	.size = 4,
53906257e9SSergio Gonzalez Monroy 	.field_index = IP6_SRC1,
54906257e9SSergio Gonzalez Monroy 	.input_index = IP6_SRC1,
55906257e9SSergio Gonzalez Monroy 	.offset = 6
56906257e9SSergio Gonzalez Monroy 	},
57906257e9SSergio Gonzalez Monroy 	{
58906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
59906257e9SSergio Gonzalez Monroy 	.size = 4,
60906257e9SSergio Gonzalez Monroy 	.field_index = IP6_SRC2,
61906257e9SSergio Gonzalez Monroy 	.input_index = IP6_SRC2,
62906257e9SSergio Gonzalez Monroy 	.offset = 10
63906257e9SSergio Gonzalez Monroy 	},
64906257e9SSergio Gonzalez Monroy 	{
65906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
66906257e9SSergio Gonzalez Monroy 	.size = 4,
67906257e9SSergio Gonzalez Monroy 	.field_index = IP6_SRC3,
68906257e9SSergio Gonzalez Monroy 	.input_index = IP6_SRC3,
69906257e9SSergio Gonzalez Monroy 	.offset = 14
70906257e9SSergio Gonzalez Monroy 	},
71906257e9SSergio Gonzalez Monroy 	{
72906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
73906257e9SSergio Gonzalez Monroy 	.size = 4,
74906257e9SSergio Gonzalez Monroy 	.field_index = IP6_DST0,
75906257e9SSergio Gonzalez Monroy 	.input_index = IP6_DST0,
76906257e9SSergio Gonzalez Monroy 	.offset = 18
77906257e9SSergio Gonzalez Monroy 	},
78906257e9SSergio Gonzalez Monroy 	{
79906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
80906257e9SSergio Gonzalez Monroy 	.size = 4,
81906257e9SSergio Gonzalez Monroy 	.field_index = IP6_DST1,
82906257e9SSergio Gonzalez Monroy 	.input_index = IP6_DST1,
83906257e9SSergio Gonzalez Monroy 	.offset = 22
84906257e9SSergio Gonzalez Monroy 	},
85906257e9SSergio Gonzalez Monroy 	{
86906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
87906257e9SSergio Gonzalez Monroy 	.size = 4,
88906257e9SSergio Gonzalez Monroy 	.field_index = IP6_DST2,
89906257e9SSergio Gonzalez Monroy 	.input_index = IP6_DST2,
90906257e9SSergio Gonzalez Monroy 	.offset = 26
91906257e9SSergio Gonzalez Monroy 	},
92906257e9SSergio Gonzalez Monroy 	{
93906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_MASK,
94906257e9SSergio Gonzalez Monroy 	.size = 4,
95906257e9SSergio Gonzalez Monroy 	.field_index = IP6_DST3,
96906257e9SSergio Gonzalez Monroy 	.input_index = IP6_DST3,
97906257e9SSergio Gonzalez Monroy 	.offset = 30
98906257e9SSergio Gonzalez Monroy 	},
99906257e9SSergio Gonzalez Monroy 	{
100906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_RANGE,
101906257e9SSergio Gonzalez Monroy 	.size = sizeof(uint16_t),
102906257e9SSergio Gonzalez Monroy 	.field_index = IP6_SRCP,
103906257e9SSergio Gonzalez Monroy 	.input_index = IP6_SRCP,
104906257e9SSergio Gonzalez Monroy 	.offset = 34
105906257e9SSergio Gonzalez Monroy 	},
106906257e9SSergio Gonzalez Monroy 	{
107906257e9SSergio Gonzalez Monroy 	.type = RTE_ACL_FIELD_TYPE_RANGE,
108906257e9SSergio Gonzalez Monroy 	.size = sizeof(uint16_t),
109906257e9SSergio Gonzalez Monroy 	.field_index = IP6_DSTP,
110906257e9SSergio Gonzalez Monroy 	.input_index = IP6_SRCP,
111906257e9SSergio Gonzalez Monroy 	.offset = 36
112906257e9SSergio Gonzalez Monroy 	}
113906257e9SSergio Gonzalez Monroy };
114906257e9SSergio Gonzalez Monroy 
115906257e9SSergio Gonzalez Monroy RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
116906257e9SSergio Gonzalez Monroy 
117b0806375SVladimir Medvedkin static struct acl6_rules *acl6_rules_out;
118d92fc70eSKonstantin Ananyev static uint32_t nb_acl6_rules_out;
119b0806375SVladimir Medvedkin static uint32_t sp_out_sz;
120906257e9SSergio Gonzalez Monroy 
121b0806375SVladimir Medvedkin static struct acl6_rules *acl6_rules_in;
122d92fc70eSKonstantin Ananyev static uint32_t nb_acl6_rules_in;
123b0806375SVladimir Medvedkin static uint32_t sp_in_sz;
124b0806375SVladimir Medvedkin 
125*9ac91e2fSRobin Jarry static struct rte_ipv6_addr
126*9ac91e2fSRobin Jarry ipv6_src_from_sp(const struct acl6_rules *rule)
127*9ac91e2fSRobin Jarry {
128*9ac91e2fSRobin Jarry 	struct rte_ipv6_addr alignas(alignof(rte_be64_t)) addr = RTE_IPV6_ADDR_UNSPEC;
129*9ac91e2fSRobin Jarry 	rte_be64_t *values = (rte_be64_t *)&addr;
130*9ac91e2fSRobin Jarry 
131*9ac91e2fSRobin Jarry 	values[0] = rte_cpu_to_be_64((uint64_t)rule->field[IP6_SRC0].value.u32 << 32 |
132*9ac91e2fSRobin Jarry 		rule->field[IP6_SRC1].value.u32);
133*9ac91e2fSRobin Jarry 	values[1] = rte_cpu_to_be_64((uint64_t)rule->field[IP6_SRC2].value.u32 << 32 |
134*9ac91e2fSRobin Jarry 		rule->field[IP6_SRC3].value.u32);
135*9ac91e2fSRobin Jarry 
136*9ac91e2fSRobin Jarry 	return addr;
137*9ac91e2fSRobin Jarry }
138*9ac91e2fSRobin Jarry 
139*9ac91e2fSRobin Jarry static struct rte_ipv6_addr
140*9ac91e2fSRobin Jarry ipv6_dst_from_sp(const struct acl6_rules *rule)
141*9ac91e2fSRobin Jarry {
142*9ac91e2fSRobin Jarry 	struct rte_ipv6_addr alignas(alignof(rte_be64_t)) addr = RTE_IPV6_ADDR_UNSPEC;
143*9ac91e2fSRobin Jarry 	rte_be64_t *values = (rte_be64_t *)&addr;
144*9ac91e2fSRobin Jarry 
145*9ac91e2fSRobin Jarry 	values[0] = rte_cpu_to_be_64((uint64_t)rule->field[IP6_DST0].value.u32 << 32 |
146*9ac91e2fSRobin Jarry 		rule->field[IP6_DST1].value.u32);
147*9ac91e2fSRobin Jarry 	values[1] = rte_cpu_to_be_64((uint64_t)rule->field[IP6_DST2].value.u32 << 32 |
148*9ac91e2fSRobin Jarry 		rule->field[IP6_DST3].value.u32);
149*9ac91e2fSRobin Jarry 
150*9ac91e2fSRobin Jarry 	return addr;
151*9ac91e2fSRobin Jarry }
152*9ac91e2fSRobin Jarry 
153*9ac91e2fSRobin Jarry static uint32_t
154*9ac91e2fSRobin Jarry ipv6_src_mask_from_sp(const struct acl6_rules *rule)
155*9ac91e2fSRobin Jarry {
156*9ac91e2fSRobin Jarry 	return rule->field[IP6_SRC0].mask_range.u32 +
157*9ac91e2fSRobin Jarry 		rule->field[IP6_SRC1].mask_range.u32 +
158*9ac91e2fSRobin Jarry 		rule->field[IP6_SRC2].mask_range.u32 +
159*9ac91e2fSRobin Jarry 		rule->field[IP6_SRC3].mask_range.u32;
160*9ac91e2fSRobin Jarry }
161*9ac91e2fSRobin Jarry 
162*9ac91e2fSRobin Jarry static uint32_t
163*9ac91e2fSRobin Jarry ipv6_dst_mask_from_sp(const struct acl6_rules *rule)
164*9ac91e2fSRobin Jarry {
165*9ac91e2fSRobin Jarry 	return rule->field[IP6_DST0].mask_range.u32 +
166*9ac91e2fSRobin Jarry 		rule->field[IP6_DST1].mask_range.u32 +
167*9ac91e2fSRobin Jarry 		rule->field[IP6_DST2].mask_range.u32 +
168*9ac91e2fSRobin Jarry 		rule->field[IP6_DST3].mask_range.u32;
169*9ac91e2fSRobin Jarry }
170*9ac91e2fSRobin Jarry 
171b0806375SVladimir Medvedkin static int
172b0806375SVladimir Medvedkin extend_sp_arr(struct acl6_rules **sp_tbl, uint32_t cur_cnt, uint32_t *cur_sz)
173b0806375SVladimir Medvedkin {
174b0806375SVladimir Medvedkin 	if (*sp_tbl == NULL) {
175b0806375SVladimir Medvedkin 		*sp_tbl = calloc(INIT_ACL_RULE_NUM, sizeof(struct acl6_rules));
176b0806375SVladimir Medvedkin 		if (*sp_tbl == NULL)
177b0806375SVladimir Medvedkin 			return -1;
178b0806375SVladimir Medvedkin 		*cur_sz = INIT_ACL_RULE_NUM;
179b0806375SVladimir Medvedkin 		return 0;
180b0806375SVladimir Medvedkin 	}
181b0806375SVladimir Medvedkin 
182b0806375SVladimir Medvedkin 	if (cur_cnt >= *cur_sz) {
183b0806375SVladimir Medvedkin 		*sp_tbl = realloc(*sp_tbl,
184b0806375SVladimir Medvedkin 			*cur_sz * sizeof(struct acl6_rules) * 2);
185b0806375SVladimir Medvedkin 		if (*sp_tbl == NULL)
186b0806375SVladimir Medvedkin 			return -1;
187b0806375SVladimir Medvedkin 		/* clean reallocated extra space */
188b0806375SVladimir Medvedkin 		memset(&(*sp_tbl)[*cur_sz], 0,
189b0806375SVladimir Medvedkin 			*cur_sz * sizeof(struct acl6_rules));
190b0806375SVladimir Medvedkin 		*cur_sz *= 2;
191b0806375SVladimir Medvedkin 	}
192b0806375SVladimir Medvedkin 
193b0806375SVladimir Medvedkin 	return 0;
194b0806375SVladimir Medvedkin }
1950d547ed0SFan Zhang 
1960d547ed0SFan Zhang void
1970d547ed0SFan Zhang parse_sp6_tokens(char **tokens, uint32_t n_tokens,
1980d547ed0SFan Zhang 	struct parse_status *status)
199906257e9SSergio Gonzalez Monroy {
2000d547ed0SFan Zhang 	struct acl6_rules *rule_ipv6 = NULL;
2010d547ed0SFan Zhang 
2020d547ed0SFan Zhang 	uint32_t *ri = NULL; /* rule index */
2030d547ed0SFan Zhang 	uint32_t ti = 0; /* token index */
20449757b68SKonstantin Ananyev 	uint32_t tv;
2050d547ed0SFan Zhang 
2060d547ed0SFan Zhang 	uint32_t esp_p = 0;
2070d547ed0SFan Zhang 	uint32_t protect_p = 0;
2080d547ed0SFan Zhang 	uint32_t bypass_p = 0;
2090d547ed0SFan Zhang 	uint32_t discard_p = 0;
2100d547ed0SFan Zhang 	uint32_t pri_p = 0;
2110d547ed0SFan Zhang 	uint32_t src_p = 0;
2120d547ed0SFan Zhang 	uint32_t dst_p = 0;
2130d547ed0SFan Zhang 	uint32_t proto_p = 0;
2140d547ed0SFan Zhang 	uint32_t sport_p = 0;
2150d547ed0SFan Zhang 	uint32_t dport_p = 0;
2160d547ed0SFan Zhang 
2170d547ed0SFan Zhang 	if (strcmp(tokens[1], "in") == 0) {
2180d547ed0SFan Zhang 		ri = &nb_acl6_rules_in;
2190d547ed0SFan Zhang 
220b0806375SVladimir Medvedkin 		if (extend_sp_arr(&acl6_rules_in, nb_acl6_rules_in,
221b0806375SVladimir Medvedkin 				&sp_in_sz) < 0)
2220d547ed0SFan Zhang 			return;
2230d547ed0SFan Zhang 
2240d547ed0SFan Zhang 		rule_ipv6 = &acl6_rules_in[*ri];
2250d547ed0SFan Zhang 
2260d547ed0SFan Zhang 	} else if (strcmp(tokens[1], "out") == 0) {
2270d547ed0SFan Zhang 		ri = &nb_acl6_rules_out;
2280d547ed0SFan Zhang 
229b0806375SVladimir Medvedkin 		if (extend_sp_arr(&acl6_rules_out, nb_acl6_rules_out,
230b0806375SVladimir Medvedkin 				&sp_out_sz) < 0)
2310d547ed0SFan Zhang 			return;
2320d547ed0SFan Zhang 
2330d547ed0SFan Zhang 		rule_ipv6 = &acl6_rules_out[*ri];
2340d547ed0SFan Zhang 
2350d547ed0SFan Zhang 	} else {
2360d547ed0SFan Zhang 		APP_CHECK(0, status, "unrecognized input \"%s\", expect"
2370d547ed0SFan Zhang 			" \"in\" or \"out\"\n", tokens[ti]);
2380d547ed0SFan Zhang 		return;
239906257e9SSergio Gonzalez Monroy 	}
2400d547ed0SFan Zhang 
2410d547ed0SFan Zhang 	rule_ipv6->data.category_mask = 1;
2420d547ed0SFan Zhang 
2430d547ed0SFan Zhang 
2440d547ed0SFan Zhang 	for (ti = 2; ti < n_tokens; ti++) {
2450d547ed0SFan Zhang 		if (strcmp(tokens[ti], "esp") == 0) {
2460d547ed0SFan Zhang 			/* currently do nothing */
2470d547ed0SFan Zhang 			APP_CHECK_PRESENCE(esp_p, tokens[ti], status);
2480d547ed0SFan Zhang 			if (status->status < 0)
2490d547ed0SFan Zhang 				return;
2500d547ed0SFan Zhang 			esp_p = 1;
2510d547ed0SFan Zhang 			continue;
2520d547ed0SFan Zhang 		}
2530d547ed0SFan Zhang 
2540d547ed0SFan Zhang 		if (strcmp(tokens[ti], "protect") == 0) {
2550d547ed0SFan Zhang 			APP_CHECK_PRESENCE(protect_p, tokens[ti], status);
2560d547ed0SFan Zhang 			if (status->status < 0)
2570d547ed0SFan Zhang 				return;
2580d547ed0SFan Zhang 			APP_CHECK(bypass_p == 0, status, "conflict item "
2590d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
2600d547ed0SFan Zhang 				"bypass");
2610d547ed0SFan Zhang 			if (status->status < 0)
2620d547ed0SFan Zhang 				return;
2630d547ed0SFan Zhang 			APP_CHECK(discard_p == 0, status, "conflict item "
2640d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
2650d547ed0SFan Zhang 				"discard");
2660d547ed0SFan Zhang 			if (status->status < 0)
2670d547ed0SFan Zhang 				return;
2680d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
2690d547ed0SFan Zhang 			if (status->status < 0)
2700d547ed0SFan Zhang 				return;
2710d547ed0SFan Zhang 			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
2720d547ed0SFan Zhang 			if (status->status < 0)
2730d547ed0SFan Zhang 				return;
2740d547ed0SFan Zhang 
27549757b68SKonstantin Ananyev 			tv = atoi(tokens[ti]);
27649757b68SKonstantin Ananyev 			APP_CHECK(tv != DISCARD && tv != BYPASS, status,
27749757b68SKonstantin Ananyev 				"invalid SPI: %s", tokens[ti]);
27849757b68SKonstantin Ananyev 			if (status->status < 0)
27949757b68SKonstantin Ananyev 				return;
28049757b68SKonstantin Ananyev 			rule_ipv6->data.userdata = tv;
2810d547ed0SFan Zhang 
2820d547ed0SFan Zhang 			protect_p = 1;
2830d547ed0SFan Zhang 			continue;
2840d547ed0SFan Zhang 		}
2850d547ed0SFan Zhang 
2860d547ed0SFan Zhang 		if (strcmp(tokens[ti], "bypass") == 0) {
2870d547ed0SFan Zhang 			APP_CHECK_PRESENCE(bypass_p, tokens[ti], status);
2880d547ed0SFan Zhang 			if (status->status < 0)
2890d547ed0SFan Zhang 				return;
2900d547ed0SFan Zhang 			APP_CHECK(protect_p == 0, status, "conflict item "
2910d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
2920d547ed0SFan Zhang 				"protect");
2930d547ed0SFan Zhang 			if (status->status < 0)
2940d547ed0SFan Zhang 				return;
2950d547ed0SFan Zhang 			APP_CHECK(discard_p == 0, status, "conflict item "
2960d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
2970d547ed0SFan Zhang 				"discard");
2980d547ed0SFan Zhang 			if (status->status < 0)
2990d547ed0SFan Zhang 				return;
3000d547ed0SFan Zhang 
3010d547ed0SFan Zhang 			rule_ipv6->data.userdata = BYPASS;
3020d547ed0SFan Zhang 
3030d547ed0SFan Zhang 			bypass_p = 1;
3040d547ed0SFan Zhang 			continue;
3050d547ed0SFan Zhang 		}
3060d547ed0SFan Zhang 
3070d547ed0SFan Zhang 		if (strcmp(tokens[ti], "discard") == 0) {
3080d547ed0SFan Zhang 			APP_CHECK_PRESENCE(discard_p, tokens[ti], status);
3090d547ed0SFan Zhang 			if (status->status < 0)
3100d547ed0SFan Zhang 				return;
3110d547ed0SFan Zhang 			APP_CHECK(protect_p == 0, status, "conflict item "
3120d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
3130d547ed0SFan Zhang 				"protect");
3140d547ed0SFan Zhang 			if (status->status < 0)
3150d547ed0SFan Zhang 				return;
3160d547ed0SFan Zhang 			APP_CHECK(bypass_p == 0, status, "conflict item "
3170d547ed0SFan Zhang 				"between \"%s\" and \"%s\"", tokens[ti],
3180d547ed0SFan Zhang 				"discard");
3190d547ed0SFan Zhang 			if (status->status < 0)
3200d547ed0SFan Zhang 				return;
3210d547ed0SFan Zhang 
3220d547ed0SFan Zhang 			rule_ipv6->data.userdata = DISCARD;
3230d547ed0SFan Zhang 
3240d547ed0SFan Zhang 			discard_p = 1;
3250d547ed0SFan Zhang 			continue;
3260d547ed0SFan Zhang 		}
3270d547ed0SFan Zhang 
3280d547ed0SFan Zhang 		if (strcmp(tokens[ti], "pri") == 0) {
3290d547ed0SFan Zhang 			APP_CHECK_PRESENCE(pri_p, tokens[ti], status);
3300d547ed0SFan Zhang 			if (status->status < 0)
3310d547ed0SFan Zhang 				return;
3320d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
3330d547ed0SFan Zhang 			if (status->status < 0)
3340d547ed0SFan Zhang 				return;
3350d547ed0SFan Zhang 			APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
3360d547ed0SFan Zhang 			if (status->status < 0)
3370d547ed0SFan Zhang 				return;
3380d547ed0SFan Zhang 
3390d547ed0SFan Zhang 			rule_ipv6->data.priority = atoi(tokens[ti]);
3400d547ed0SFan Zhang 
3410d547ed0SFan Zhang 			pri_p = 1;
3420d547ed0SFan Zhang 			continue;
3430d547ed0SFan Zhang 		}
3440d547ed0SFan Zhang 
3450d547ed0SFan Zhang 		if (strcmp(tokens[ti], "src") == 0) {
346*9ac91e2fSRobin Jarry 			struct rte_ipv6_addr ip;
3470d547ed0SFan Zhang 			uint32_t depth;
3480d547ed0SFan Zhang 
3490d547ed0SFan Zhang 			APP_CHECK_PRESENCE(src_p, tokens[ti], status);
3500d547ed0SFan Zhang 			if (status->status < 0)
3510d547ed0SFan Zhang 				return;
3520d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
3530d547ed0SFan Zhang 			if (status->status < 0)
3540d547ed0SFan Zhang 				return;
3550d547ed0SFan Zhang 
3560d547ed0SFan Zhang 			APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
3570d547ed0SFan Zhang 				&depth) == 0, status, "unrecognized "
3580d547ed0SFan Zhang 				"input \"%s\", expect valid ipv6 "
3590d547ed0SFan Zhang 				"addr", tokens[ti]);
3600d547ed0SFan Zhang 			if (status->status < 0)
3610d547ed0SFan Zhang 				return;
3620d547ed0SFan Zhang 
3630d547ed0SFan Zhang 			rule_ipv6->field[1].value.u32 =
364*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[0] << 24 |
365*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[1] << 16 |
366*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[2] << 8 |
367*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[3];
3680d547ed0SFan Zhang 			rule_ipv6->field[1].mask_range.u32 =
3690d547ed0SFan Zhang 				(depth > 32) ? 32 : depth;
3700d547ed0SFan Zhang 			depth = (depth > 32) ? (depth - 32) : 0;
3710d547ed0SFan Zhang 			rule_ipv6->field[2].value.u32 =
372*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[4] << 24 |
373*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[5] << 16 |
374*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[6] << 8 |
375*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[7];
3760d547ed0SFan Zhang 			rule_ipv6->field[2].mask_range.u32 =
3770d547ed0SFan Zhang 				(depth > 32) ? 32 : depth;
3780d547ed0SFan Zhang 			depth = (depth > 32) ? (depth - 32) : 0;
3790d547ed0SFan Zhang 			rule_ipv6->field[3].value.u32 =
380*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[8] << 24 |
381*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[9] << 16 |
382*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[10] << 8 |
383*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[11];
3840d547ed0SFan Zhang 			rule_ipv6->field[3].mask_range.u32 =
3850d547ed0SFan Zhang 				(depth > 32) ? 32 : depth;
3860d547ed0SFan Zhang 			depth = (depth > 32) ? (depth - 32) : 0;
3870d547ed0SFan Zhang 			rule_ipv6->field[4].value.u32 =
388*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[12] << 24 |
389*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[13] << 16 |
390*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[14] << 8 |
391*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[15];
3920d547ed0SFan Zhang 			rule_ipv6->field[4].mask_range.u32 =
3930d547ed0SFan Zhang 				(depth > 32) ? 32 : depth;
3940d547ed0SFan Zhang 
3950d547ed0SFan Zhang 			src_p = 1;
3960d547ed0SFan Zhang 			continue;
3970d547ed0SFan Zhang 		}
3980d547ed0SFan Zhang 
3990d547ed0SFan Zhang 		if (strcmp(tokens[ti], "dst") == 0) {
400*9ac91e2fSRobin Jarry 			struct rte_ipv6_addr ip;
4010d547ed0SFan Zhang 			uint32_t depth;
4020d547ed0SFan Zhang 
4030d547ed0SFan Zhang 			APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
4040d547ed0SFan Zhang 			if (status->status < 0)
4050d547ed0SFan Zhang 				return;
4060d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
4070d547ed0SFan Zhang 			if (status->status < 0)
4080d547ed0SFan Zhang 				return;
4090d547ed0SFan Zhang 
4100d547ed0SFan Zhang 			APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
4110d547ed0SFan Zhang 				&depth) == 0, status, "unrecognized "
4120d547ed0SFan Zhang 				"input \"%s\", expect valid ipv6 "
4130d547ed0SFan Zhang 				"addr", tokens[ti]);
4140d547ed0SFan Zhang 			if (status->status < 0)
4150d547ed0SFan Zhang 				return;
4160d547ed0SFan Zhang 
4170d547ed0SFan Zhang 			rule_ipv6->field[5].value.u32 =
418*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[0] << 24 |
419*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[1] << 16 |
420*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[2] << 8 |
421*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[3];
4220d547ed0SFan Zhang 			rule_ipv6->field[5].mask_range.u32 =
4230d547ed0SFan Zhang 				(depth > 32) ? 32 : depth;
4240d547ed0SFan Zhang 			depth = (depth > 32) ? (depth - 32) : 0;
4250d547ed0SFan Zhang 			rule_ipv6->field[6].value.u32 =
426*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[4] << 24 |
427*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[5] << 16 |
428*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[6] << 8 |
429*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[7];
4300d547ed0SFan Zhang 			rule_ipv6->field[6].mask_range.u32 =
4310d547ed0SFan Zhang 				(depth > 32) ? 32 : depth;
4320d547ed0SFan Zhang 			depth = (depth > 32) ? (depth - 32) : 0;
4330d547ed0SFan Zhang 			rule_ipv6->field[7].value.u32 =
434*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[8] << 24 |
435*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[9] << 16 |
436*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[10] << 8 |
437*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[11];
4380d547ed0SFan Zhang 			rule_ipv6->field[7].mask_range.u32 =
4390d547ed0SFan Zhang 				(depth > 32) ? 32 : depth;
4400d547ed0SFan Zhang 			depth = (depth > 32) ? (depth - 32) : 0;
4410d547ed0SFan Zhang 			rule_ipv6->field[8].value.u32 =
442*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[12] << 24 |
443*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[13] << 16 |
444*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[14] << 8 |
445*9ac91e2fSRobin Jarry 				(uint32_t)ip.a[15];
4460d547ed0SFan Zhang 			rule_ipv6->field[8].mask_range.u32 =
4470d547ed0SFan Zhang 				(depth > 32) ? 32 : depth;
4480d547ed0SFan Zhang 
4490d547ed0SFan Zhang 			dst_p = 1;
4500d547ed0SFan Zhang 			continue;
4510d547ed0SFan Zhang 		}
4520d547ed0SFan Zhang 
4530d547ed0SFan Zhang 		if (strcmp(tokens[ti], "proto") == 0) {
4540d547ed0SFan Zhang 			uint16_t low, high;
4550d547ed0SFan Zhang 
4560d547ed0SFan Zhang 			APP_CHECK_PRESENCE(proto_p, tokens[ti], status);
4570d547ed0SFan Zhang 			if (status->status < 0)
4580d547ed0SFan Zhang 				return;
4590d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
4600d547ed0SFan Zhang 			if (status->status < 0)
4610d547ed0SFan Zhang 				return;
4620d547ed0SFan Zhang 
4630d547ed0SFan Zhang 			APP_CHECK(parse_range(tokens[ti], &low, &high)
4640d547ed0SFan Zhang 				== 0, status, "unrecognized input \"%s\""
4650d547ed0SFan Zhang 				", expect \"from:to\"", tokens[ti]);
4660d547ed0SFan Zhang 			if (status->status < 0)
4670d547ed0SFan Zhang 				return;
4680d547ed0SFan Zhang 			APP_CHECK(low <= 0xff, status, "proto low "
4690d547ed0SFan Zhang 				"over-limit");
4700d547ed0SFan Zhang 			if (status->status < 0)
4710d547ed0SFan Zhang 				return;
4720d547ed0SFan Zhang 			APP_CHECK(high <= 0xff, status, "proto high "
4730d547ed0SFan Zhang 				"over-limit");
4740d547ed0SFan Zhang 			if (status->status < 0)
4750d547ed0SFan Zhang 				return;
4760d547ed0SFan Zhang 
4770d547ed0SFan Zhang 			rule_ipv6->field[0].value.u8 = (uint8_t)low;
4780d547ed0SFan Zhang 			rule_ipv6->field[0].mask_range.u8 = (uint8_t)high;
4790d547ed0SFan Zhang 
4800d547ed0SFan Zhang 			proto_p = 1;
4810d547ed0SFan Zhang 			continue;
4820d547ed0SFan Zhang 		}
4830d547ed0SFan Zhang 
4840d547ed0SFan Zhang 		if (strcmp(tokens[ti], "sport") == 0) {
4850d547ed0SFan Zhang 			uint16_t port_low, port_high;
4860d547ed0SFan Zhang 
4870d547ed0SFan Zhang 			APP_CHECK_PRESENCE(sport_p, tokens[ti], status);
4880d547ed0SFan Zhang 			if (status->status < 0)
4890d547ed0SFan Zhang 				return;
4900d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
4910d547ed0SFan Zhang 			if (status->status < 0)
4920d547ed0SFan Zhang 				return;
4930d547ed0SFan Zhang 
4940d547ed0SFan Zhang 			APP_CHECK(parse_range(tokens[ti], &port_low,
4950d547ed0SFan Zhang 				&port_high) == 0, status, "unrecognized "
4960d547ed0SFan Zhang 				"input \"%s\", expect \"port_from:"
4970d547ed0SFan Zhang 				"port_to\"", tokens[ti]);
4980d547ed0SFan Zhang 			if (status->status < 0)
4990d547ed0SFan Zhang 				return;
5000d547ed0SFan Zhang 
5010d547ed0SFan Zhang 			rule_ipv6->field[9].value.u16 = port_low;
5020d547ed0SFan Zhang 			rule_ipv6->field[9].mask_range.u16 = port_high;
5030d547ed0SFan Zhang 
5040d547ed0SFan Zhang 			sport_p = 1;
5050d547ed0SFan Zhang 			continue;
5060d547ed0SFan Zhang 		}
5070d547ed0SFan Zhang 
5080d547ed0SFan Zhang 		if (strcmp(tokens[ti], "dport") == 0) {
5090d547ed0SFan Zhang 			uint16_t port_low, port_high;
5100d547ed0SFan Zhang 
5110d547ed0SFan Zhang 			APP_CHECK_PRESENCE(dport_p, tokens[ti], status);
5120d547ed0SFan Zhang 			if (status->status < 0)
5130d547ed0SFan Zhang 				return;
5140d547ed0SFan Zhang 			INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
5150d547ed0SFan Zhang 			if (status->status < 0)
5160d547ed0SFan Zhang 				return;
5170d547ed0SFan Zhang 
5180d547ed0SFan Zhang 			APP_CHECK(parse_range(tokens[ti], &port_low,
5190d547ed0SFan Zhang 				&port_high) == 0, status, "unrecognized "
5200d547ed0SFan Zhang 				"input \"%s\", expect \"port_from:"
5210d547ed0SFan Zhang 				"port_to\"", tokens[ti]);
5220d547ed0SFan Zhang 			if (status->status < 0)
5230d547ed0SFan Zhang 				return;
5240d547ed0SFan Zhang 
5250d547ed0SFan Zhang 			rule_ipv6->field[10].value.u16 = port_low;
5260d547ed0SFan Zhang 			rule_ipv6->field[10].mask_range.u16 = port_high;
5270d547ed0SFan Zhang 
5280d547ed0SFan Zhang 			dport_p = 1;
5290d547ed0SFan Zhang 			continue;
5300d547ed0SFan Zhang 		}
5310d547ed0SFan Zhang 
5327be78d02SJosh Soref 		/* unrecognizable input */
5330d547ed0SFan Zhang 		APP_CHECK(0, status, "unrecognized input \"%s\"",
5340d547ed0SFan Zhang 			tokens[ti]);
5350d547ed0SFan Zhang 		return;
5360d547ed0SFan Zhang 	}
5370d547ed0SFan Zhang 
5380d547ed0SFan Zhang 	/* check if argument(s) are missing */
5390d547ed0SFan Zhang 	APP_CHECK(esp_p == 1, status, "missing argument \"esp\"");
5400d547ed0SFan Zhang 	if (status->status < 0)
5410d547ed0SFan Zhang 		return;
5420d547ed0SFan Zhang 
5430d547ed0SFan Zhang 	APP_CHECK(protect_p | bypass_p | discard_p, status, "missing "
5440d547ed0SFan Zhang 		"argument \"protect\", \"bypass\", or \"discard\"");
5450d547ed0SFan Zhang 	if (status->status < 0)
5460d547ed0SFan Zhang 		return;
5470d547ed0SFan Zhang 
5480d547ed0SFan Zhang 	*ri = *ri + 1;
5490d547ed0SFan Zhang }
550906257e9SSergio Gonzalez Monroy 
551906257e9SSergio Gonzalez Monroy static inline void
552906257e9SSergio Gonzalez Monroy print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra)
553906257e9SSergio Gonzalez Monroy {
554906257e9SSergio Gonzalez Monroy 	uint8_t a, b, c, d;
555906257e9SSergio Gonzalez Monroy 
556906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[IP6_SRC0].value.u32,
557906257e9SSergio Gonzalez Monroy 		&a, &b, &c, &d);
558906257e9SSergio Gonzalez Monroy 	printf("%.2x%.2x:%.2x%.2x", a, b, c, d);
559906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[IP6_SRC1].value.u32,
560906257e9SSergio Gonzalez Monroy 		&a, &b, &c, &d);
561906257e9SSergio Gonzalez Monroy 	printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
562906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[IP6_SRC2].value.u32,
563906257e9SSergio Gonzalez Monroy 		&a, &b, &c, &d);
564906257e9SSergio Gonzalez Monroy 	printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
565906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[IP6_SRC3].value.u32,
566906257e9SSergio Gonzalez Monroy 		&a, &b, &c, &d);
567906257e9SSergio Gonzalez Monroy 	printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d,
568906257e9SSergio Gonzalez Monroy 			rule->field[IP6_SRC0].mask_range.u32
569906257e9SSergio Gonzalez Monroy 			+ rule->field[IP6_SRC1].mask_range.u32
570906257e9SSergio Gonzalez Monroy 			+ rule->field[IP6_SRC2].mask_range.u32
571906257e9SSergio Gonzalez Monroy 			+ rule->field[IP6_SRC3].mask_range.u32);
572906257e9SSergio Gonzalez Monroy 
573906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[IP6_DST0].value.u32,
574906257e9SSergio Gonzalez Monroy 		&a, &b, &c, &d);
575906257e9SSergio Gonzalez Monroy 	printf("%.2x%.2x:%.2x%.2x", a, b, c, d);
576906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[IP6_DST1].value.u32,
577906257e9SSergio Gonzalez Monroy 		&a, &b, &c, &d);
578906257e9SSergio Gonzalez Monroy 	printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
579906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[IP6_DST2].value.u32,
580906257e9SSergio Gonzalez Monroy 		&a, &b, &c, &d);
581906257e9SSergio Gonzalez Monroy 	printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
582906257e9SSergio Gonzalez Monroy 	uint32_t_to_char(rule->field[IP6_DST3].value.u32,
583906257e9SSergio Gonzalez Monroy 		&a, &b, &c, &d);
584906257e9SSergio Gonzalez Monroy 	printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d,
585906257e9SSergio Gonzalez Monroy 			rule->field[IP6_DST0].mask_range.u32
586906257e9SSergio Gonzalez Monroy 			+ rule->field[IP6_DST1].mask_range.u32
587906257e9SSergio Gonzalez Monroy 			+ rule->field[IP6_DST2].mask_range.u32
588906257e9SSergio Gonzalez Monroy 			+ rule->field[IP6_DST3].mask_range.u32);
589906257e9SSergio Gonzalez Monroy 
590906257e9SSergio Gonzalez Monroy 	printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
591906257e9SSergio Gonzalez Monroy 		rule->field[IP6_SRCP].value.u16,
592906257e9SSergio Gonzalez Monroy 		rule->field[IP6_SRCP].mask_range.u16,
593906257e9SSergio Gonzalez Monroy 		rule->field[IP6_DSTP].value.u16,
594906257e9SSergio Gonzalez Monroy 		rule->field[IP6_DSTP].mask_range.u16,
595906257e9SSergio Gonzalez Monroy 		rule->field[IP6_PROTO].value.u8,
596906257e9SSergio Gonzalez Monroy 		rule->field[IP6_PROTO].mask_range.u8);
597906257e9SSergio Gonzalez Monroy 	if (extra)
598906257e9SSergio Gonzalez Monroy 		printf("0x%x-0x%x-0x%x ",
599906257e9SSergio Gonzalez Monroy 			rule->data.category_mask,
600906257e9SSergio Gonzalez Monroy 			rule->data.priority,
601906257e9SSergio Gonzalez Monroy 			rule->data.userdata);
602906257e9SSergio Gonzalez Monroy }
603906257e9SSergio Gonzalez Monroy 
604906257e9SSergio Gonzalez Monroy static inline void
605906257e9SSergio Gonzalez Monroy dump_ip6_rules(const struct acl6_rules *rule, int32_t num, int32_t extra)
606906257e9SSergio Gonzalez Monroy {
607906257e9SSergio Gonzalez Monroy 	int32_t i;
608906257e9SSergio Gonzalez Monroy 
609906257e9SSergio Gonzalez Monroy 	for (i = 0; i < num; i++, rule++) {
610906257e9SSergio Gonzalez Monroy 		printf("\t%d:", i + 1);
611906257e9SSergio Gonzalez Monroy 		print_one_ip6_rule(rule, extra);
612906257e9SSergio Gonzalez Monroy 		printf("\n");
613906257e9SSergio Gonzalez Monroy 	}
614906257e9SSergio Gonzalez Monroy }
615906257e9SSergio Gonzalez Monroy 
616906257e9SSergio Gonzalez Monroy static struct rte_acl_ctx *
617906257e9SSergio Gonzalez Monroy acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
618906257e9SSergio Gonzalez Monroy 		uint32_t rules_nb)
619906257e9SSergio Gonzalez Monroy {
620906257e9SSergio Gonzalez Monroy 	char s[PATH_MAX];
621906257e9SSergio Gonzalez Monroy 	struct rte_acl_param acl_param;
622906257e9SSergio Gonzalez Monroy 	struct rte_acl_config acl_build_param;
623906257e9SSergio Gonzalez Monroy 	struct rte_acl_ctx *ctx;
624906257e9SSergio Gonzalez Monroy 
625b0806375SVladimir Medvedkin 	printf("Creating SP context with %u rules\n", rules_nb);
626906257e9SSergio Gonzalez Monroy 
627906257e9SSergio Gonzalez Monroy 	memset(&acl_param, 0, sizeof(acl_param));
628906257e9SSergio Gonzalez Monroy 
629906257e9SSergio Gonzalez Monroy 	/* Create ACL contexts */
630906257e9SSergio Gonzalez Monroy 	snprintf(s, sizeof(s), "%s_%d", name, socketid);
631906257e9SSergio Gonzalez Monroy 
632906257e9SSergio Gonzalez Monroy 	printf("IPv4 %s entries [%u]:\n", s, rules_nb);
633906257e9SSergio Gonzalez Monroy 	dump_ip6_rules(rules, rules_nb, 1);
634906257e9SSergio Gonzalez Monroy 
635906257e9SSergio Gonzalez Monroy 	acl_param.name = s;
636906257e9SSergio Gonzalez Monroy 	acl_param.socket_id = socketid;
637906257e9SSergio Gonzalez Monroy 	acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs));
638b0806375SVladimir Medvedkin 	acl_param.max_rule_num = rules_nb;
639906257e9SSergio Gonzalez Monroy 
640906257e9SSergio Gonzalez Monroy 	ctx = rte_acl_create(&acl_param);
641906257e9SSergio Gonzalez Monroy 	if (ctx == NULL)
642906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Failed to create ACL context\n");
643906257e9SSergio Gonzalez Monroy 
644906257e9SSergio Gonzalez Monroy 	if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules,
645906257e9SSergio Gonzalez Monroy 				rules_nb) < 0)
646906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "add rules failed\n");
647906257e9SSergio Gonzalez Monroy 
648906257e9SSergio Gonzalez Monroy 	/* Perform builds */
649906257e9SSergio Gonzalez Monroy 	memset(&acl_build_param, 0, sizeof(acl_build_param));
650906257e9SSergio Gonzalez Monroy 
651906257e9SSergio Gonzalez Monroy 	acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;
652906257e9SSergio Gonzalez Monroy 	acl_build_param.num_fields = RTE_DIM(ip6_defs);
653906257e9SSergio Gonzalez Monroy 	memcpy(&acl_build_param.defs, ip6_defs, sizeof(ip6_defs));
654906257e9SSergio Gonzalez Monroy 
655906257e9SSergio Gonzalez Monroy 	if (rte_acl_build(ctx, &acl_build_param) != 0)
656906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n");
657906257e9SSergio Gonzalez Monroy 
658906257e9SSergio Gonzalez Monroy 	rte_acl_dump(ctx);
659906257e9SSergio Gonzalez Monroy 
660906257e9SSergio Gonzalez Monroy 	return ctx;
661906257e9SSergio Gonzalez Monroy }
662906257e9SSergio Gonzalez Monroy 
66349757b68SKonstantin Ananyev /*
66449757b68SKonstantin Ananyev  * check that for each rule it's SPI has a correspondent entry in SAD
66549757b68SKonstantin Ananyev  */
66649757b68SKonstantin Ananyev static int
667df3e1d94SVladimir Medvedkin check_spi_value(struct sa_ctx *sa_ctx, int inbound)
66849757b68SKonstantin Ananyev {
66949757b68SKonstantin Ananyev 	uint32_t i, num, spi;
670df3e1d94SVladimir Medvedkin 	int32_t spi_idx;
671df3e1d94SVladimir Medvedkin 	struct acl6_rules *acr;
67249757b68SKonstantin Ananyev 
67349757b68SKonstantin Ananyev 	if (inbound != 0) {
67449757b68SKonstantin Ananyev 		acr = acl6_rules_in;
67549757b68SKonstantin Ananyev 		num = nb_acl6_rules_in;
67649757b68SKonstantin Ananyev 	} else {
67749757b68SKonstantin Ananyev 		acr = acl6_rules_out;
67849757b68SKonstantin Ananyev 		num = nb_acl6_rules_out;
67949757b68SKonstantin Ananyev 	}
68049757b68SKonstantin Ananyev 
68149757b68SKonstantin Ananyev 	for (i = 0; i != num; i++) {
68249757b68SKonstantin Ananyev 		spi = acr[i].data.userdata;
683df3e1d94SVladimir Medvedkin 		if (spi != DISCARD && spi != BYPASS) {
684df3e1d94SVladimir Medvedkin 			spi_idx = sa_spi_present(sa_ctx, spi, inbound);
685df3e1d94SVladimir Medvedkin 			if (spi_idx < 0) {
686df3e1d94SVladimir Medvedkin 				RTE_LOG(ERR, IPSEC,
687df3e1d94SVladimir Medvedkin 					"SPI %u is not present in SAD\n",
68849757b68SKonstantin Ananyev 					spi);
68949757b68SKonstantin Ananyev 				return -ENOENT;
69049757b68SKonstantin Ananyev 			}
691df3e1d94SVladimir Medvedkin 			/* Update userdata with spi index */
692df3e1d94SVladimir Medvedkin 			acr[i].data.userdata = spi_idx + 1;
693df3e1d94SVladimir Medvedkin 		}
69449757b68SKonstantin Ananyev 	}
69549757b68SKonstantin Ananyev 
69649757b68SKonstantin Ananyev 	return 0;
69749757b68SKonstantin Ananyev }
69849757b68SKonstantin Ananyev 
699906257e9SSergio Gonzalez Monroy void
7000d547ed0SFan Zhang sp6_init(struct socket_ctx *ctx, int32_t socket_id)
701906257e9SSergio Gonzalez Monroy {
702906257e9SSergio Gonzalez Monroy 	const char *name;
703906257e9SSergio Gonzalez Monroy 
704906257e9SSergio Gonzalez Monroy 	if (ctx == NULL)
705906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "NULL context.\n");
706906257e9SSergio Gonzalez Monroy 
707906257e9SSergio Gonzalez Monroy 	if (ctx->sp_ip6_in != NULL)
708906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Inbound IPv6 SP DB for socket %u "
709906257e9SSergio Gonzalez Monroy 				"already initialized\n", socket_id);
710906257e9SSergio Gonzalez Monroy 
711906257e9SSergio Gonzalez Monroy 	if (ctx->sp_ip6_out != NULL)
712906257e9SSergio Gonzalez Monroy 		rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
713906257e9SSergio Gonzalez Monroy 				"already initialized\n", socket_id);
714906257e9SSergio Gonzalez Monroy 
715df3e1d94SVladimir Medvedkin 	if (check_spi_value(ctx->sa_in, 1) < 0)
71649757b68SKonstantin Ananyev 		rte_exit(EXIT_FAILURE,
71749757b68SKonstantin Ananyev 			"Inbound IPv6 SP DB has unmatched in SAD SPIs\n");
71849757b68SKonstantin Ananyev 
719df3e1d94SVladimir Medvedkin 	if (check_spi_value(ctx->sa_out, 0) < 0)
72049757b68SKonstantin Ananyev 		rte_exit(EXIT_FAILURE,
72149757b68SKonstantin Ananyev 			"Outbound IPv6 SP DB has unmatched in SAD SPIs\n");
72249757b68SKonstantin Ananyev 
7230d547ed0SFan Zhang 	if (nb_acl6_rules_in > 0) {
724906257e9SSergio Gonzalez Monroy 		name = "sp_ip6_in";
7250d547ed0SFan Zhang 		ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name,
7260d547ed0SFan Zhang 			socket_id, acl6_rules_in, nb_acl6_rules_in);
7270d547ed0SFan Zhang 	} else
7280d547ed0SFan Zhang 		RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule "
7290d547ed0SFan Zhang 			"specified\n");
730906257e9SSergio Gonzalez Monroy 
7310d547ed0SFan Zhang 	if (nb_acl6_rules_out > 0) {
732906257e9SSergio Gonzalez Monroy 		name = "sp_ip6_out";
7330d547ed0SFan Zhang 		ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name,
7340d547ed0SFan Zhang 			socket_id, acl6_rules_out, nb_acl6_rules_out);
7350d547ed0SFan Zhang 	} else
7360d547ed0SFan Zhang 		RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule "
7370d547ed0SFan Zhang 			"specified\n");
738906257e9SSergio Gonzalez Monroy }
7395a032a71SKonstantin Ananyev 
740b0806375SVladimir Medvedkin static int
741b0806375SVladimir Medvedkin sp_cmp(const void *p, const void *q)
742b0806375SVladimir Medvedkin {
743b0806375SVladimir Medvedkin 	uint32_t spi1 = ((const struct acl6_rules *)p)->data.userdata;
744b0806375SVladimir Medvedkin 	uint32_t spi2 = ((const struct acl6_rules *)q)->data.userdata;
745b0806375SVladimir Medvedkin 
746b0806375SVladimir Medvedkin 	return (int)(spi1 - spi2);
747b0806375SVladimir Medvedkin }
748b0806375SVladimir Medvedkin 
7495a032a71SKonstantin Ananyev /*
7505a032a71SKonstantin Ananyev  * Search though SP rules for given SPI.
7515a032a71SKonstantin Ananyev  */
7525a032a71SKonstantin Ananyev int
753b1a3ac78SMariusz Drost sp6_spi_present(uint32_t spi, int inbound, struct ip_addr ip_addr[2],
754b1a3ac78SMariusz Drost 			uint32_t mask[2])
7555a032a71SKonstantin Ananyev {
756b0806375SVladimir Medvedkin 	uint32_t num;
757b0806375SVladimir Medvedkin 	struct acl6_rules *rule;
7585a032a71SKonstantin Ananyev 	const struct acl6_rules *acr;
759b0806375SVladimir Medvedkin 	struct acl6_rules tmpl;
7605a032a71SKonstantin Ananyev 
7615a032a71SKonstantin Ananyev 	if (inbound != 0) {
7625a032a71SKonstantin Ananyev 		acr = acl6_rules_in;
7635a032a71SKonstantin Ananyev 		num = nb_acl6_rules_in;
7645a032a71SKonstantin Ananyev 	} else {
7655a032a71SKonstantin Ananyev 		acr = acl6_rules_out;
7665a032a71SKonstantin Ananyev 		num = nb_acl6_rules_out;
7675a032a71SKonstantin Ananyev 	}
7685a032a71SKonstantin Ananyev 
769b0806375SVladimir Medvedkin 	tmpl.data.userdata = spi;
770b0806375SVladimir Medvedkin 
771b0806375SVladimir Medvedkin 	rule = bsearch(&tmpl, acr, num, sizeof(struct acl6_rules), sp_cmp);
772b0806375SVladimir Medvedkin 	if (rule != NULL) {
773b1a3ac78SMariusz Drost 		if (NULL != ip_addr && NULL != mask) {
774*9ac91e2fSRobin Jarry 			ip_addr[0].ip.ip6 = ipv6_src_from_sp(rule);
775*9ac91e2fSRobin Jarry 			ip_addr[1].ip.ip6 = ipv6_dst_from_sp(rule);
776*9ac91e2fSRobin Jarry 			mask[0] = ipv6_src_mask_from_sp(rule);
777*9ac91e2fSRobin Jarry 			mask[1] = ipv6_dst_mask_from_sp(rule);
778b1a3ac78SMariusz Drost 		}
779b0806375SVladimir Medvedkin 		return RTE_PTR_DIFF(rule, acr) / sizeof(struct acl6_rules);
780b1a3ac78SMariusz Drost 	}
7815a032a71SKonstantin Ananyev 
7825a032a71SKonstantin Ananyev 	return -ENOENT;
7835a032a71SKonstantin Ananyev }
784b0806375SVladimir Medvedkin 
785b0806375SVladimir Medvedkin void
786b0806375SVladimir Medvedkin sp6_sort_arr(void)
787b0806375SVladimir Medvedkin {
788b0806375SVladimir Medvedkin 	qsort(acl6_rules_in, nb_acl6_rules_in, sizeof(struct acl6_rules),
789b0806375SVladimir Medvedkin 		sp_cmp);
790b0806375SVladimir Medvedkin 	qsort(acl6_rules_out, nb_acl6_rules_out, sizeof(struct acl6_rules),
791b0806375SVladimir Medvedkin 		sp_cmp);
792b0806375SVladimir Medvedkin }
793