]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2016 Intel Corporation | |
7c673cae FG |
3 | */ |
4 | ||
5 | /* | |
6 | * Security Policies | |
7 | */ | |
8 | #include <sys/types.h> | |
9 | #include <netinet/in.h> | |
10 | #include <netinet/ip6.h> | |
11 | ||
12 | #include <rte_acl.h> | |
13 | #include <rte_ip.h> | |
14 | ||
15 | #include "ipsec.h" | |
16 | #include "parser.h" | |
17 | ||
18 | #define MAX_ACL_RULE_NUM 1024 | |
19 | ||
20 | enum { | |
21 | IP6_PROTO, | |
22 | IP6_SRC0, | |
23 | IP6_SRC1, | |
24 | IP6_SRC2, | |
25 | IP6_SRC3, | |
26 | IP6_DST0, | |
27 | IP6_DST1, | |
28 | IP6_DST2, | |
29 | IP6_DST3, | |
30 | IP6_SRCP, | |
31 | IP6_DSTP, | |
32 | IP6_NUM | |
33 | }; | |
34 | ||
35 | #define IP6_ADDR_SIZE 16 | |
36 | ||
9f95a23c | 37 | static struct rte_acl_field_def ip6_defs[IP6_NUM] = { |
7c673cae FG |
38 | { |
39 | .type = RTE_ACL_FIELD_TYPE_BITMASK, | |
40 | .size = sizeof(uint8_t), | |
41 | .field_index = IP6_PROTO, | |
42 | .input_index = IP6_PROTO, | |
43 | .offset = 0, | |
44 | }, | |
45 | { | |
46 | .type = RTE_ACL_FIELD_TYPE_MASK, | |
47 | .size = 4, | |
48 | .field_index = IP6_SRC0, | |
49 | .input_index = IP6_SRC0, | |
50 | .offset = 2 | |
51 | }, | |
52 | { | |
53 | .type = RTE_ACL_FIELD_TYPE_MASK, | |
54 | .size = 4, | |
55 | .field_index = IP6_SRC1, | |
56 | .input_index = IP6_SRC1, | |
57 | .offset = 6 | |
58 | }, | |
59 | { | |
60 | .type = RTE_ACL_FIELD_TYPE_MASK, | |
61 | .size = 4, | |
62 | .field_index = IP6_SRC2, | |
63 | .input_index = IP6_SRC2, | |
64 | .offset = 10 | |
65 | }, | |
66 | { | |
67 | .type = RTE_ACL_FIELD_TYPE_MASK, | |
68 | .size = 4, | |
69 | .field_index = IP6_SRC3, | |
70 | .input_index = IP6_SRC3, | |
71 | .offset = 14 | |
72 | }, | |
73 | { | |
74 | .type = RTE_ACL_FIELD_TYPE_MASK, | |
75 | .size = 4, | |
76 | .field_index = IP6_DST0, | |
77 | .input_index = IP6_DST0, | |
78 | .offset = 18 | |
79 | }, | |
80 | { | |
81 | .type = RTE_ACL_FIELD_TYPE_MASK, | |
82 | .size = 4, | |
83 | .field_index = IP6_DST1, | |
84 | .input_index = IP6_DST1, | |
85 | .offset = 22 | |
86 | }, | |
87 | { | |
88 | .type = RTE_ACL_FIELD_TYPE_MASK, | |
89 | .size = 4, | |
90 | .field_index = IP6_DST2, | |
91 | .input_index = IP6_DST2, | |
92 | .offset = 26 | |
93 | }, | |
94 | { | |
95 | .type = RTE_ACL_FIELD_TYPE_MASK, | |
96 | .size = 4, | |
97 | .field_index = IP6_DST3, | |
98 | .input_index = IP6_DST3, | |
99 | .offset = 30 | |
100 | }, | |
101 | { | |
102 | .type = RTE_ACL_FIELD_TYPE_RANGE, | |
103 | .size = sizeof(uint16_t), | |
104 | .field_index = IP6_SRCP, | |
105 | .input_index = IP6_SRCP, | |
106 | .offset = 34 | |
107 | }, | |
108 | { | |
109 | .type = RTE_ACL_FIELD_TYPE_RANGE, | |
110 | .size = sizeof(uint16_t), | |
111 | .field_index = IP6_DSTP, | |
112 | .input_index = IP6_SRCP, | |
113 | .offset = 36 | |
114 | } | |
115 | }; | |
116 | ||
117 | RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs)); | |
118 | ||
9f95a23c TL |
119 | static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM]; |
120 | static uint32_t nb_acl6_rules_out; | |
7c673cae | 121 | |
9f95a23c TL |
122 | static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM]; |
123 | static uint32_t nb_acl6_rules_in; | |
7c673cae FG |
124 | |
125 | void | |
126 | parse_sp6_tokens(char **tokens, uint32_t n_tokens, | |
127 | struct parse_status *status) | |
128 | { | |
129 | struct acl6_rules *rule_ipv6 = NULL; | |
130 | ||
131 | uint32_t *ri = NULL; /* rule index */ | |
132 | uint32_t ti = 0; /* token index */ | |
9f95a23c | 133 | uint32_t tv; |
7c673cae FG |
134 | |
135 | uint32_t esp_p = 0; | |
136 | uint32_t protect_p = 0; | |
137 | uint32_t bypass_p = 0; | |
138 | uint32_t discard_p = 0; | |
139 | uint32_t pri_p = 0; | |
140 | uint32_t src_p = 0; | |
141 | uint32_t dst_p = 0; | |
142 | uint32_t proto_p = 0; | |
143 | uint32_t sport_p = 0; | |
144 | uint32_t dport_p = 0; | |
145 | ||
146 | if (strcmp(tokens[1], "in") == 0) { | |
147 | ri = &nb_acl6_rules_in; | |
148 | ||
149 | APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too " | |
150 | "many sp rules, abort insertion\n"); | |
151 | if (status->status < 0) | |
152 | return; | |
153 | ||
154 | rule_ipv6 = &acl6_rules_in[*ri]; | |
155 | ||
156 | } else if (strcmp(tokens[1], "out") == 0) { | |
157 | ri = &nb_acl6_rules_out; | |
158 | ||
159 | APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too " | |
160 | "many sp rules, abort insertion\n"); | |
161 | if (status->status < 0) | |
162 | return; | |
163 | ||
164 | rule_ipv6 = &acl6_rules_out[*ri]; | |
165 | ||
166 | } else { | |
167 | APP_CHECK(0, status, "unrecognized input \"%s\", expect" | |
168 | " \"in\" or \"out\"\n", tokens[ti]); | |
169 | return; | |
170 | } | |
171 | ||
172 | rule_ipv6->data.category_mask = 1; | |
173 | ||
174 | ||
175 | for (ti = 2; ti < n_tokens; ti++) { | |
176 | if (strcmp(tokens[ti], "esp") == 0) { | |
177 | /* currently do nothing */ | |
178 | APP_CHECK_PRESENCE(esp_p, tokens[ti], status); | |
179 | if (status->status < 0) | |
180 | return; | |
181 | esp_p = 1; | |
182 | continue; | |
183 | } | |
184 | ||
185 | if (strcmp(tokens[ti], "protect") == 0) { | |
186 | APP_CHECK_PRESENCE(protect_p, tokens[ti], status); | |
187 | if (status->status < 0) | |
188 | return; | |
189 | APP_CHECK(bypass_p == 0, status, "conflict item " | |
190 | "between \"%s\" and \"%s\"", tokens[ti], | |
191 | "bypass"); | |
192 | if (status->status < 0) | |
193 | return; | |
194 | APP_CHECK(discard_p == 0, status, "conflict item " | |
195 | "between \"%s\" and \"%s\"", tokens[ti], | |
196 | "discard"); | |
197 | if (status->status < 0) | |
198 | return; | |
199 | INCREMENT_TOKEN_INDEX(ti, n_tokens, status); | |
200 | if (status->status < 0) | |
201 | return; | |
202 | APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); | |
203 | if (status->status < 0) | |
204 | return; | |
205 | ||
9f95a23c TL |
206 | tv = atoi(tokens[ti]); |
207 | APP_CHECK(tv != DISCARD && tv != BYPASS, status, | |
208 | "invalid SPI: %s", tokens[ti]); | |
209 | if (status->status < 0) | |
210 | return; | |
211 | rule_ipv6->data.userdata = tv; | |
7c673cae FG |
212 | |
213 | protect_p = 1; | |
214 | continue; | |
215 | } | |
216 | ||
217 | if (strcmp(tokens[ti], "bypass") == 0) { | |
218 | APP_CHECK_PRESENCE(bypass_p, tokens[ti], status); | |
219 | if (status->status < 0) | |
220 | return; | |
221 | APP_CHECK(protect_p == 0, status, "conflict item " | |
222 | "between \"%s\" and \"%s\"", tokens[ti], | |
223 | "protect"); | |
224 | if (status->status < 0) | |
225 | return; | |
226 | APP_CHECK(discard_p == 0, status, "conflict item " | |
227 | "between \"%s\" and \"%s\"", tokens[ti], | |
228 | "discard"); | |
229 | if (status->status < 0) | |
230 | return; | |
231 | ||
232 | rule_ipv6->data.userdata = BYPASS; | |
233 | ||
234 | bypass_p = 1; | |
235 | continue; | |
236 | } | |
237 | ||
238 | if (strcmp(tokens[ti], "discard") == 0) { | |
239 | APP_CHECK_PRESENCE(discard_p, tokens[ti], status); | |
240 | if (status->status < 0) | |
241 | return; | |
242 | APP_CHECK(protect_p == 0, status, "conflict item " | |
243 | "between \"%s\" and \"%s\"", tokens[ti], | |
244 | "protect"); | |
245 | if (status->status < 0) | |
246 | return; | |
247 | APP_CHECK(bypass_p == 0, status, "conflict item " | |
248 | "between \"%s\" and \"%s\"", tokens[ti], | |
249 | "discard"); | |
250 | if (status->status < 0) | |
251 | return; | |
252 | ||
253 | rule_ipv6->data.userdata = DISCARD; | |
254 | ||
255 | discard_p = 1; | |
256 | continue; | |
257 | } | |
258 | ||
259 | if (strcmp(tokens[ti], "pri") == 0) { | |
260 | APP_CHECK_PRESENCE(pri_p, tokens[ti], status); | |
261 | if (status->status < 0) | |
262 | return; | |
263 | INCREMENT_TOKEN_INDEX(ti, n_tokens, status); | |
264 | if (status->status < 0) | |
265 | return; | |
266 | APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); | |
267 | if (status->status < 0) | |
268 | return; | |
269 | ||
270 | rule_ipv6->data.priority = atoi(tokens[ti]); | |
271 | ||
272 | pri_p = 1; | |
273 | continue; | |
274 | } | |
275 | ||
276 | if (strcmp(tokens[ti], "src") == 0) { | |
277 | struct in6_addr ip; | |
278 | uint32_t depth; | |
279 | ||
280 | APP_CHECK_PRESENCE(src_p, tokens[ti], status); | |
281 | if (status->status < 0) | |
282 | return; | |
283 | INCREMENT_TOKEN_INDEX(ti, n_tokens, status); | |
284 | if (status->status < 0) | |
285 | return; | |
286 | ||
287 | APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, | |
288 | &depth) == 0, status, "unrecognized " | |
289 | "input \"%s\", expect valid ipv6 " | |
290 | "addr", tokens[ti]); | |
291 | if (status->status < 0) | |
292 | return; | |
293 | ||
294 | rule_ipv6->field[1].value.u32 = | |
295 | (uint32_t)ip.s6_addr[0] << 24 | | |
296 | (uint32_t)ip.s6_addr[1] << 16 | | |
297 | (uint32_t)ip.s6_addr[2] << 8 | | |
298 | (uint32_t)ip.s6_addr[3]; | |
299 | rule_ipv6->field[1].mask_range.u32 = | |
300 | (depth > 32) ? 32 : depth; | |
301 | depth = (depth > 32) ? (depth - 32) : 0; | |
302 | rule_ipv6->field[2].value.u32 = | |
303 | (uint32_t)ip.s6_addr[4] << 24 | | |
304 | (uint32_t)ip.s6_addr[5] << 16 | | |
305 | (uint32_t)ip.s6_addr[6] << 8 | | |
306 | (uint32_t)ip.s6_addr[7]; | |
307 | rule_ipv6->field[2].mask_range.u32 = | |
308 | (depth > 32) ? 32 : depth; | |
309 | depth = (depth > 32) ? (depth - 32) : 0; | |
310 | rule_ipv6->field[3].value.u32 = | |
311 | (uint32_t)ip.s6_addr[8] << 24 | | |
312 | (uint32_t)ip.s6_addr[9] << 16 | | |
313 | (uint32_t)ip.s6_addr[10] << 8 | | |
314 | (uint32_t)ip.s6_addr[11]; | |
315 | rule_ipv6->field[3].mask_range.u32 = | |
316 | (depth > 32) ? 32 : depth; | |
317 | depth = (depth > 32) ? (depth - 32) : 0; | |
318 | rule_ipv6->field[4].value.u32 = | |
319 | (uint32_t)ip.s6_addr[12] << 24 | | |
320 | (uint32_t)ip.s6_addr[13] << 16 | | |
321 | (uint32_t)ip.s6_addr[14] << 8 | | |
322 | (uint32_t)ip.s6_addr[15]; | |
323 | rule_ipv6->field[4].mask_range.u32 = | |
324 | (depth > 32) ? 32 : depth; | |
325 | ||
326 | src_p = 1; | |
327 | continue; | |
328 | } | |
329 | ||
330 | if (strcmp(tokens[ti], "dst") == 0) { | |
331 | struct in6_addr ip; | |
332 | uint32_t depth; | |
333 | ||
334 | APP_CHECK_PRESENCE(dst_p, tokens[ti], status); | |
335 | if (status->status < 0) | |
336 | return; | |
337 | INCREMENT_TOKEN_INDEX(ti, n_tokens, status); | |
338 | if (status->status < 0) | |
339 | return; | |
340 | ||
341 | APP_CHECK(parse_ipv6_addr(tokens[ti], &ip, | |
342 | &depth) == 0, status, "unrecognized " | |
343 | "input \"%s\", expect valid ipv6 " | |
344 | "addr", tokens[ti]); | |
345 | if (status->status < 0) | |
346 | return; | |
347 | ||
348 | rule_ipv6->field[5].value.u32 = | |
349 | (uint32_t)ip.s6_addr[0] << 24 | | |
350 | (uint32_t)ip.s6_addr[1] << 16 | | |
351 | (uint32_t)ip.s6_addr[2] << 8 | | |
352 | (uint32_t)ip.s6_addr[3]; | |
353 | rule_ipv6->field[5].mask_range.u32 = | |
354 | (depth > 32) ? 32 : depth; | |
355 | depth = (depth > 32) ? (depth - 32) : 0; | |
356 | rule_ipv6->field[6].value.u32 = | |
357 | (uint32_t)ip.s6_addr[4] << 24 | | |
358 | (uint32_t)ip.s6_addr[5] << 16 | | |
359 | (uint32_t)ip.s6_addr[6] << 8 | | |
360 | (uint32_t)ip.s6_addr[7]; | |
361 | rule_ipv6->field[6].mask_range.u32 = | |
362 | (depth > 32) ? 32 : depth; | |
363 | depth = (depth > 32) ? (depth - 32) : 0; | |
364 | rule_ipv6->field[7].value.u32 = | |
365 | (uint32_t)ip.s6_addr[8] << 24 | | |
366 | (uint32_t)ip.s6_addr[9] << 16 | | |
367 | (uint32_t)ip.s6_addr[10] << 8 | | |
368 | (uint32_t)ip.s6_addr[11]; | |
369 | rule_ipv6->field[7].mask_range.u32 = | |
370 | (depth > 32) ? 32 : depth; | |
371 | depth = (depth > 32) ? (depth - 32) : 0; | |
372 | rule_ipv6->field[8].value.u32 = | |
373 | (uint32_t)ip.s6_addr[12] << 24 | | |
374 | (uint32_t)ip.s6_addr[13] << 16 | | |
375 | (uint32_t)ip.s6_addr[14] << 8 | | |
376 | (uint32_t)ip.s6_addr[15]; | |
377 | rule_ipv6->field[8].mask_range.u32 = | |
378 | (depth > 32) ? 32 : depth; | |
379 | ||
380 | dst_p = 1; | |
381 | continue; | |
382 | } | |
383 | ||
384 | if (strcmp(tokens[ti], "proto") == 0) { | |
385 | uint16_t low, high; | |
386 | ||
387 | APP_CHECK_PRESENCE(proto_p, tokens[ti], status); | |
388 | if (status->status < 0) | |
389 | return; | |
390 | INCREMENT_TOKEN_INDEX(ti, n_tokens, status); | |
391 | if (status->status < 0) | |
392 | return; | |
393 | ||
394 | APP_CHECK(parse_range(tokens[ti], &low, &high) | |
395 | == 0, status, "unrecognized input \"%s\"" | |
396 | ", expect \"from:to\"", tokens[ti]); | |
397 | if (status->status < 0) | |
398 | return; | |
399 | APP_CHECK(low <= 0xff, status, "proto low " | |
400 | "over-limit"); | |
401 | if (status->status < 0) | |
402 | return; | |
403 | APP_CHECK(high <= 0xff, status, "proto high " | |
404 | "over-limit"); | |
405 | if (status->status < 0) | |
406 | return; | |
407 | ||
408 | rule_ipv6->field[0].value.u8 = (uint8_t)low; | |
409 | rule_ipv6->field[0].mask_range.u8 = (uint8_t)high; | |
410 | ||
411 | proto_p = 1; | |
412 | continue; | |
413 | } | |
414 | ||
415 | if (strcmp(tokens[ti], "sport") == 0) { | |
416 | uint16_t port_low, port_high; | |
417 | ||
418 | APP_CHECK_PRESENCE(sport_p, tokens[ti], status); | |
419 | if (status->status < 0) | |
420 | return; | |
421 | INCREMENT_TOKEN_INDEX(ti, n_tokens, status); | |
422 | if (status->status < 0) | |
423 | return; | |
424 | ||
425 | APP_CHECK(parse_range(tokens[ti], &port_low, | |
426 | &port_high) == 0, status, "unrecognized " | |
427 | "input \"%s\", expect \"port_from:" | |
428 | "port_to\"", tokens[ti]); | |
429 | if (status->status < 0) | |
430 | return; | |
431 | ||
432 | rule_ipv6->field[9].value.u16 = port_low; | |
433 | rule_ipv6->field[9].mask_range.u16 = port_high; | |
434 | ||
435 | sport_p = 1; | |
436 | continue; | |
437 | } | |
438 | ||
439 | if (strcmp(tokens[ti], "dport") == 0) { | |
440 | uint16_t port_low, port_high; | |
441 | ||
442 | APP_CHECK_PRESENCE(dport_p, tokens[ti], status); | |
443 | if (status->status < 0) | |
444 | return; | |
445 | INCREMENT_TOKEN_INDEX(ti, n_tokens, status); | |
446 | if (status->status < 0) | |
447 | return; | |
448 | ||
449 | APP_CHECK(parse_range(tokens[ti], &port_low, | |
450 | &port_high) == 0, status, "unrecognized " | |
451 | "input \"%s\", expect \"port_from:" | |
452 | "port_to\"", tokens[ti]); | |
453 | if (status->status < 0) | |
454 | return; | |
455 | ||
456 | rule_ipv6->field[10].value.u16 = port_low; | |
457 | rule_ipv6->field[10].mask_range.u16 = port_high; | |
458 | ||
459 | dport_p = 1; | |
460 | continue; | |
461 | } | |
462 | ||
463 | /* unrecognizeable input */ | |
464 | APP_CHECK(0, status, "unrecognized input \"%s\"", | |
465 | tokens[ti]); | |
466 | return; | |
467 | } | |
468 | ||
469 | /* check if argument(s) are missing */ | |
470 | APP_CHECK(esp_p == 1, status, "missing argument \"esp\""); | |
471 | if (status->status < 0) | |
472 | return; | |
473 | ||
474 | APP_CHECK(protect_p | bypass_p | discard_p, status, "missing " | |
475 | "argument \"protect\", \"bypass\", or \"discard\""); | |
476 | if (status->status < 0) | |
477 | return; | |
478 | ||
479 | *ri = *ri + 1; | |
480 | } | |
481 | ||
482 | static inline void | |
483 | print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra) | |
484 | { | |
485 | uint8_t a, b, c, d; | |
486 | ||
487 | uint32_t_to_char(rule->field[IP6_SRC0].value.u32, | |
488 | &a, &b, &c, &d); | |
489 | printf("%.2x%.2x:%.2x%.2x", a, b, c, d); | |
490 | uint32_t_to_char(rule->field[IP6_SRC1].value.u32, | |
491 | &a, &b, &c, &d); | |
492 | printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); | |
493 | uint32_t_to_char(rule->field[IP6_SRC2].value.u32, | |
494 | &a, &b, &c, &d); | |
495 | printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); | |
496 | uint32_t_to_char(rule->field[IP6_SRC3].value.u32, | |
497 | &a, &b, &c, &d); | |
498 | printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, | |
499 | rule->field[IP6_SRC0].mask_range.u32 | |
500 | + rule->field[IP6_SRC1].mask_range.u32 | |
501 | + rule->field[IP6_SRC2].mask_range.u32 | |
502 | + rule->field[IP6_SRC3].mask_range.u32); | |
503 | ||
504 | uint32_t_to_char(rule->field[IP6_DST0].value.u32, | |
505 | &a, &b, &c, &d); | |
506 | printf("%.2x%.2x:%.2x%.2x", a, b, c, d); | |
507 | uint32_t_to_char(rule->field[IP6_DST1].value.u32, | |
508 | &a, &b, &c, &d); | |
509 | printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); | |
510 | uint32_t_to_char(rule->field[IP6_DST2].value.u32, | |
511 | &a, &b, &c, &d); | |
512 | printf(":%.2x%.2x:%.2x%.2x", a, b, c, d); | |
513 | uint32_t_to_char(rule->field[IP6_DST3].value.u32, | |
514 | &a, &b, &c, &d); | |
515 | printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d, | |
516 | rule->field[IP6_DST0].mask_range.u32 | |
517 | + rule->field[IP6_DST1].mask_range.u32 | |
518 | + rule->field[IP6_DST2].mask_range.u32 | |
519 | + rule->field[IP6_DST3].mask_range.u32); | |
520 | ||
521 | printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ", | |
522 | rule->field[IP6_SRCP].value.u16, | |
523 | rule->field[IP6_SRCP].mask_range.u16, | |
524 | rule->field[IP6_DSTP].value.u16, | |
525 | rule->field[IP6_DSTP].mask_range.u16, | |
526 | rule->field[IP6_PROTO].value.u8, | |
527 | rule->field[IP6_PROTO].mask_range.u8); | |
528 | if (extra) | |
529 | printf("0x%x-0x%x-0x%x ", | |
530 | rule->data.category_mask, | |
531 | rule->data.priority, | |
532 | rule->data.userdata); | |
533 | } | |
534 | ||
535 | static inline void | |
536 | dump_ip6_rules(const struct acl6_rules *rule, int32_t num, int32_t extra) | |
537 | { | |
538 | int32_t i; | |
539 | ||
540 | for (i = 0; i < num; i++, rule++) { | |
541 | printf("\t%d:", i + 1); | |
542 | print_one_ip6_rule(rule, extra); | |
543 | printf("\n"); | |
544 | } | |
545 | } | |
546 | ||
547 | static struct rte_acl_ctx * | |
548 | acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules, | |
549 | uint32_t rules_nb) | |
550 | { | |
551 | char s[PATH_MAX]; | |
552 | struct rte_acl_param acl_param; | |
553 | struct rte_acl_config acl_build_param; | |
554 | struct rte_acl_ctx *ctx; | |
555 | ||
556 | printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM); | |
557 | ||
558 | memset(&acl_param, 0, sizeof(acl_param)); | |
559 | ||
560 | /* Create ACL contexts */ | |
561 | snprintf(s, sizeof(s), "%s_%d", name, socketid); | |
562 | ||
563 | printf("IPv4 %s entries [%u]:\n", s, rules_nb); | |
564 | dump_ip6_rules(rules, rules_nb, 1); | |
565 | ||
566 | acl_param.name = s; | |
567 | acl_param.socket_id = socketid; | |
568 | acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs)); | |
569 | acl_param.max_rule_num = MAX_ACL_RULE_NUM; | |
570 | ||
571 | ctx = rte_acl_create(&acl_param); | |
572 | if (ctx == NULL) | |
573 | rte_exit(EXIT_FAILURE, "Failed to create ACL context\n"); | |
574 | ||
575 | if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules, | |
576 | rules_nb) < 0) | |
577 | rte_exit(EXIT_FAILURE, "add rules failed\n"); | |
578 | ||
579 | /* Perform builds */ | |
580 | memset(&acl_build_param, 0, sizeof(acl_build_param)); | |
581 | ||
582 | acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES; | |
583 | acl_build_param.num_fields = RTE_DIM(ip6_defs); | |
584 | memcpy(&acl_build_param.defs, ip6_defs, sizeof(ip6_defs)); | |
585 | ||
586 | if (rte_acl_build(ctx, &acl_build_param) != 0) | |
587 | rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n"); | |
588 | ||
589 | rte_acl_dump(ctx); | |
590 | ||
591 | return ctx; | |
592 | } | |
593 | ||
9f95a23c TL |
594 | /* |
595 | * check that for each rule it's SPI has a correspondent entry in SAD | |
596 | */ | |
597 | static int | |
598 | check_spi_value(int inbound) | |
599 | { | |
600 | uint32_t i, num, spi; | |
601 | const struct acl6_rules *acr; | |
602 | ||
603 | if (inbound != 0) { | |
604 | acr = acl6_rules_in; | |
605 | num = nb_acl6_rules_in; | |
606 | } else { | |
607 | acr = acl6_rules_out; | |
608 | num = nb_acl6_rules_out; | |
609 | } | |
610 | ||
611 | for (i = 0; i != num; i++) { | |
612 | spi = acr[i].data.userdata; | |
613 | if (spi != DISCARD && spi != BYPASS && | |
614 | sa_spi_present(spi, inbound) < 0) { | |
615 | RTE_LOG(ERR, IPSEC, "SPI %u is not present in SAD\n", | |
616 | spi); | |
617 | return -ENOENT; | |
618 | } | |
619 | } | |
620 | ||
621 | return 0; | |
622 | } | |
623 | ||
7c673cae FG |
624 | void |
625 | sp6_init(struct socket_ctx *ctx, int32_t socket_id) | |
626 | { | |
627 | const char *name; | |
628 | ||
629 | if (ctx == NULL) | |
630 | rte_exit(EXIT_FAILURE, "NULL context.\n"); | |
631 | ||
632 | if (ctx->sp_ip6_in != NULL) | |
633 | rte_exit(EXIT_FAILURE, "Inbound IPv6 SP DB for socket %u " | |
634 | "already initialized\n", socket_id); | |
635 | ||
636 | if (ctx->sp_ip6_out != NULL) | |
637 | rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u " | |
638 | "already initialized\n", socket_id); | |
639 | ||
9f95a23c TL |
640 | if (check_spi_value(1) < 0) |
641 | rte_exit(EXIT_FAILURE, | |
642 | "Inbound IPv6 SP DB has unmatched in SAD SPIs\n"); | |
643 | ||
644 | if (check_spi_value(0) < 0) | |
645 | rte_exit(EXIT_FAILURE, | |
646 | "Outbound IPv6 SP DB has unmatched in SAD SPIs\n"); | |
647 | ||
7c673cae FG |
648 | if (nb_acl6_rules_in > 0) { |
649 | name = "sp_ip6_in"; | |
650 | ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name, | |
651 | socket_id, acl6_rules_in, nb_acl6_rules_in); | |
652 | } else | |
653 | RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule " | |
654 | "specified\n"); | |
655 | ||
656 | if (nb_acl6_rules_out > 0) { | |
657 | name = "sp_ip6_out"; | |
658 | ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name, | |
659 | socket_id, acl6_rules_out, nb_acl6_rules_out); | |
660 | } else | |
661 | RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule " | |
662 | "specified\n"); | |
663 | } | |
9f95a23c TL |
664 | |
665 | /* | |
666 | * Search though SP rules for given SPI. | |
667 | */ | |
668 | int | |
669 | sp6_spi_present(uint32_t spi, int inbound) | |
670 | { | |
671 | uint32_t i, num; | |
672 | const struct acl6_rules *acr; | |
673 | ||
674 | if (inbound != 0) { | |
675 | acr = acl6_rules_in; | |
676 | num = nb_acl6_rules_in; | |
677 | } else { | |
678 | acr = acl6_rules_out; | |
679 | num = nb_acl6_rules_out; | |
680 | } | |
681 | ||
682 | for (i = 0; i != num; i++) { | |
683 | if (acr[i].data.userdata == spi) | |
684 | return i; | |
685 | } | |
686 | ||
687 | return -ENOENT; | |
688 | } |