Imported Upstream version 16.11
[deb_dpdk.git] / examples / ipsec-secgw / sp6.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2016 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 /*
35  * Security Policies
36  */
37 #include <sys/types.h>
38 #include <netinet/in.h>
39 #include <netinet/ip6.h>
40
41 #include <rte_acl.h>
42 #include <rte_ip.h>
43
44 #include "ipsec.h"
45 #include "parser.h"
46
47 #define MAX_ACL_RULE_NUM        1024
48
49 enum {
50         IP6_PROTO,
51         IP6_SRC0,
52         IP6_SRC1,
53         IP6_SRC2,
54         IP6_SRC3,
55         IP6_DST0,
56         IP6_DST1,
57         IP6_DST2,
58         IP6_DST3,
59         IP6_SRCP,
60         IP6_DSTP,
61         IP6_NUM
62 };
63
64 #define IP6_ADDR_SIZE 16
65
66 struct rte_acl_field_def ip6_defs[IP6_NUM] = {
67         {
68         .type = RTE_ACL_FIELD_TYPE_BITMASK,
69         .size = sizeof(uint8_t),
70         .field_index = IP6_PROTO,
71         .input_index = IP6_PROTO,
72         .offset = 0,
73         },
74         {
75         .type = RTE_ACL_FIELD_TYPE_MASK,
76         .size = 4,
77         .field_index = IP6_SRC0,
78         .input_index = IP6_SRC0,
79         .offset = 2
80         },
81         {
82         .type = RTE_ACL_FIELD_TYPE_MASK,
83         .size = 4,
84         .field_index = IP6_SRC1,
85         .input_index = IP6_SRC1,
86         .offset = 6
87         },
88         {
89         .type = RTE_ACL_FIELD_TYPE_MASK,
90         .size = 4,
91         .field_index = IP6_SRC2,
92         .input_index = IP6_SRC2,
93         .offset = 10
94         },
95         {
96         .type = RTE_ACL_FIELD_TYPE_MASK,
97         .size = 4,
98         .field_index = IP6_SRC3,
99         .input_index = IP6_SRC3,
100         .offset = 14
101         },
102         {
103         .type = RTE_ACL_FIELD_TYPE_MASK,
104         .size = 4,
105         .field_index = IP6_DST0,
106         .input_index = IP6_DST0,
107         .offset = 18
108         },
109         {
110         .type = RTE_ACL_FIELD_TYPE_MASK,
111         .size = 4,
112         .field_index = IP6_DST1,
113         .input_index = IP6_DST1,
114         .offset = 22
115         },
116         {
117         .type = RTE_ACL_FIELD_TYPE_MASK,
118         .size = 4,
119         .field_index = IP6_DST2,
120         .input_index = IP6_DST2,
121         .offset = 26
122         },
123         {
124         .type = RTE_ACL_FIELD_TYPE_MASK,
125         .size = 4,
126         .field_index = IP6_DST3,
127         .input_index = IP6_DST3,
128         .offset = 30
129         },
130         {
131         .type = RTE_ACL_FIELD_TYPE_RANGE,
132         .size = sizeof(uint16_t),
133         .field_index = IP6_SRCP,
134         .input_index = IP6_SRCP,
135         .offset = 34
136         },
137         {
138         .type = RTE_ACL_FIELD_TYPE_RANGE,
139         .size = sizeof(uint16_t),
140         .field_index = IP6_DSTP,
141         .input_index = IP6_SRCP,
142         .offset = 36
143         }
144 };
145
146 RTE_ACL_RULE_DEF(acl6_rules, RTE_DIM(ip6_defs));
147
148 struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
149 uint32_t nb_acl6_rules_out;
150
151 struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
152 uint32_t nb_acl6_rules_in;
153
154 void
155 parse_sp6_tokens(char **tokens, uint32_t n_tokens,
156         struct parse_status *status)
157 {
158         struct acl6_rules *rule_ipv6 = NULL;
159
160         uint32_t *ri = NULL; /* rule index */
161         uint32_t ti = 0; /* token index */
162
163         uint32_t esp_p = 0;
164         uint32_t protect_p = 0;
165         uint32_t bypass_p = 0;
166         uint32_t discard_p = 0;
167         uint32_t pri_p = 0;
168         uint32_t src_p = 0;
169         uint32_t dst_p = 0;
170         uint32_t proto_p = 0;
171         uint32_t sport_p = 0;
172         uint32_t dport_p = 0;
173
174         if (strcmp(tokens[1], "in") == 0) {
175                 ri = &nb_acl6_rules_in;
176
177                 APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
178                         "many sp rules, abort insertion\n");
179                 if (status->status < 0)
180                         return;
181
182                 rule_ipv6 = &acl6_rules_in[*ri];
183
184         } else if (strcmp(tokens[1], "out") == 0) {
185                 ri = &nb_acl6_rules_out;
186
187                 APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, "too "
188                         "many sp rules, abort insertion\n");
189                 if (status->status < 0)
190                         return;
191
192                 rule_ipv6 = &acl6_rules_out[*ri];
193
194         } else {
195                 APP_CHECK(0, status, "unrecognized input \"%s\", expect"
196                         " \"in\" or \"out\"\n", tokens[ti]);
197                 return;
198         }
199
200         rule_ipv6->data.category_mask = 1;
201
202
203         for (ti = 2; ti < n_tokens; ti++) {
204                 if (strcmp(tokens[ti], "esp") == 0) {
205                         /* currently do nothing */
206                         APP_CHECK_PRESENCE(esp_p, tokens[ti], status);
207                         if (status->status < 0)
208                                 return;
209                         esp_p = 1;
210                         continue;
211                 }
212
213                 if (strcmp(tokens[ti], "protect") == 0) {
214                         APP_CHECK_PRESENCE(protect_p, tokens[ti], status);
215                         if (status->status < 0)
216                                 return;
217                         APP_CHECK(bypass_p == 0, status, "conflict item "
218                                 "between \"%s\" and \"%s\"", tokens[ti],
219                                 "bypass");
220                         if (status->status < 0)
221                                 return;
222                         APP_CHECK(discard_p == 0, status, "conflict item "
223                                 "between \"%s\" and \"%s\"", tokens[ti],
224                                 "discard");
225                         if (status->status < 0)
226                                 return;
227                         INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
228                         if (status->status < 0)
229                                 return;
230                         APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
231                         if (status->status < 0)
232                                 return;
233
234                         rule_ipv6->data.userdata =
235                                 PROTECT(atoi(tokens[ti]));
236
237                         protect_p = 1;
238                         continue;
239                 }
240
241                 if (strcmp(tokens[ti], "bypass") == 0) {
242                         APP_CHECK_PRESENCE(bypass_p, tokens[ti], status);
243                         if (status->status < 0)
244                                 return;
245                         APP_CHECK(protect_p == 0, status, "conflict item "
246                                 "between \"%s\" and \"%s\"", tokens[ti],
247                                 "protect");
248                         if (status->status < 0)
249                                 return;
250                         APP_CHECK(discard_p == 0, status, "conflict item "
251                                 "between \"%s\" and \"%s\"", tokens[ti],
252                                 "discard");
253                         if (status->status < 0)
254                                 return;
255
256                         rule_ipv6->data.userdata = BYPASS;
257
258                         bypass_p = 1;
259                         continue;
260                 }
261
262                 if (strcmp(tokens[ti], "discard") == 0) {
263                         APP_CHECK_PRESENCE(discard_p, tokens[ti], status);
264                         if (status->status < 0)
265                                 return;
266                         APP_CHECK(protect_p == 0, status, "conflict item "
267                                 "between \"%s\" and \"%s\"", tokens[ti],
268                                 "protect");
269                         if (status->status < 0)
270                                 return;
271                         APP_CHECK(bypass_p == 0, status, "conflict item "
272                                 "between \"%s\" and \"%s\"", tokens[ti],
273                                 "discard");
274                         if (status->status < 0)
275                                 return;
276
277                         rule_ipv6->data.userdata = DISCARD;
278
279                         discard_p = 1;
280                         continue;
281                 }
282
283                 if (strcmp(tokens[ti], "pri") == 0) {
284                         APP_CHECK_PRESENCE(pri_p, tokens[ti], status);
285                         if (status->status < 0)
286                                 return;
287                         INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
288                         if (status->status < 0)
289                                 return;
290                         APP_CHECK_TOKEN_IS_NUM(tokens, ti, status);
291                         if (status->status < 0)
292                                 return;
293
294                         rule_ipv6->data.priority = atoi(tokens[ti]);
295
296                         pri_p = 1;
297                         continue;
298                 }
299
300                 if (strcmp(tokens[ti], "src") == 0) {
301                         struct in6_addr ip;
302                         uint32_t depth;
303
304                         APP_CHECK_PRESENCE(src_p, tokens[ti], status);
305                         if (status->status < 0)
306                                 return;
307                         INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
308                         if (status->status < 0)
309                                 return;
310
311                         APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
312                                 &depth) == 0, status, "unrecognized "
313                                 "input \"%s\", expect valid ipv6 "
314                                 "addr", tokens[ti]);
315                         if (status->status < 0)
316                                 return;
317
318                         rule_ipv6->field[1].value.u32 =
319                                 (uint32_t)ip.s6_addr[0] << 24 |
320                                 (uint32_t)ip.s6_addr[1] << 16 |
321                                 (uint32_t)ip.s6_addr[2] << 8 |
322                                 (uint32_t)ip.s6_addr[3];
323                         rule_ipv6->field[1].mask_range.u32 =
324                                 (depth > 32) ? 32 : depth;
325                         depth = (depth > 32) ? (depth - 32) : 0;
326                         rule_ipv6->field[2].value.u32 =
327                                 (uint32_t)ip.s6_addr[4] << 24 |
328                                 (uint32_t)ip.s6_addr[5] << 16 |
329                                 (uint32_t)ip.s6_addr[6] << 8 |
330                                 (uint32_t)ip.s6_addr[7];
331                         rule_ipv6->field[2].mask_range.u32 =
332                                 (depth > 32) ? 32 : depth;
333                         depth = (depth > 32) ? (depth - 32) : 0;
334                         rule_ipv6->field[3].value.u32 =
335                                 (uint32_t)ip.s6_addr[8] << 24 |
336                                 (uint32_t)ip.s6_addr[9] << 16 |
337                                 (uint32_t)ip.s6_addr[10] << 8 |
338                                 (uint32_t)ip.s6_addr[11];
339                         rule_ipv6->field[3].mask_range.u32 =
340                                 (depth > 32) ? 32 : depth;
341                         depth = (depth > 32) ? (depth - 32) : 0;
342                         rule_ipv6->field[4].value.u32 =
343                                 (uint32_t)ip.s6_addr[12] << 24 |
344                                 (uint32_t)ip.s6_addr[13] << 16 |
345                                 (uint32_t)ip.s6_addr[14] << 8 |
346                                 (uint32_t)ip.s6_addr[15];
347                         rule_ipv6->field[4].mask_range.u32 =
348                                 (depth > 32) ? 32 : depth;
349
350                         src_p = 1;
351                         continue;
352                 }
353
354                 if (strcmp(tokens[ti], "dst") == 0) {
355                         struct in6_addr ip;
356                         uint32_t depth;
357
358                         APP_CHECK_PRESENCE(dst_p, tokens[ti], status);
359                         if (status->status < 0)
360                                 return;
361                         INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
362                         if (status->status < 0)
363                                 return;
364
365                         APP_CHECK(parse_ipv6_addr(tokens[ti], &ip,
366                                 &depth) == 0, status, "unrecognized "
367                                 "input \"%s\", expect valid ipv6 "
368                                 "addr", tokens[ti]);
369                         if (status->status < 0)
370                                 return;
371
372                         rule_ipv6->field[5].value.u32 =
373                                 (uint32_t)ip.s6_addr[0] << 24 |
374                                 (uint32_t)ip.s6_addr[1] << 16 |
375                                 (uint32_t)ip.s6_addr[2] << 8 |
376                                 (uint32_t)ip.s6_addr[3];
377                         rule_ipv6->field[5].mask_range.u32 =
378                                 (depth > 32) ? 32 : depth;
379                         depth = (depth > 32) ? (depth - 32) : 0;
380                         rule_ipv6->field[6].value.u32 =
381                                 (uint32_t)ip.s6_addr[4] << 24 |
382                                 (uint32_t)ip.s6_addr[5] << 16 |
383                                 (uint32_t)ip.s6_addr[6] << 8 |
384                                 (uint32_t)ip.s6_addr[7];
385                         rule_ipv6->field[6].mask_range.u32 =
386                                 (depth > 32) ? 32 : depth;
387                         depth = (depth > 32) ? (depth - 32) : 0;
388                         rule_ipv6->field[7].value.u32 =
389                                 (uint32_t)ip.s6_addr[8] << 24 |
390                                 (uint32_t)ip.s6_addr[9] << 16 |
391                                 (uint32_t)ip.s6_addr[10] << 8 |
392                                 (uint32_t)ip.s6_addr[11];
393                         rule_ipv6->field[7].mask_range.u32 =
394                                 (depth > 32) ? 32 : depth;
395                         depth = (depth > 32) ? (depth - 32) : 0;
396                         rule_ipv6->field[8].value.u32 =
397                                 (uint32_t)ip.s6_addr[12] << 24 |
398                                 (uint32_t)ip.s6_addr[13] << 16 |
399                                 (uint32_t)ip.s6_addr[14] << 8 |
400                                 (uint32_t)ip.s6_addr[15];
401                         rule_ipv6->field[8].mask_range.u32 =
402                                 (depth > 32) ? 32 : depth;
403
404                         dst_p = 1;
405                         continue;
406                 }
407
408                 if (strcmp(tokens[ti], "proto") == 0) {
409                         uint16_t low, high;
410
411                         APP_CHECK_PRESENCE(proto_p, tokens[ti], status);
412                         if (status->status < 0)
413                                 return;
414                         INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
415                         if (status->status < 0)
416                                 return;
417
418                         APP_CHECK(parse_range(tokens[ti], &low, &high)
419                                 == 0, status, "unrecognized input \"%s\""
420                                 ", expect \"from:to\"", tokens[ti]);
421                         if (status->status < 0)
422                                 return;
423                         APP_CHECK(low <= 0xff, status, "proto low "
424                                 "over-limit");
425                         if (status->status < 0)
426                                 return;
427                         APP_CHECK(high <= 0xff, status, "proto high "
428                                 "over-limit");
429                         if (status->status < 0)
430                                 return;
431
432                         rule_ipv6->field[0].value.u8 = (uint8_t)low;
433                         rule_ipv6->field[0].mask_range.u8 = (uint8_t)high;
434
435                         proto_p = 1;
436                         continue;
437                 }
438
439                 if (strcmp(tokens[ti], "sport") == 0) {
440                         uint16_t port_low, port_high;
441
442                         APP_CHECK_PRESENCE(sport_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[9].value.u16 = port_low;
457                         rule_ipv6->field[9].mask_range.u16 = port_high;
458
459                         sport_p = 1;
460                         continue;
461                 }
462
463                 if (strcmp(tokens[ti], "dport") == 0) {
464                         uint16_t port_low, port_high;
465
466                         APP_CHECK_PRESENCE(dport_p, tokens[ti], status);
467                         if (status->status < 0)
468                                 return;
469                         INCREMENT_TOKEN_INDEX(ti, n_tokens, status);
470                         if (status->status < 0)
471                                 return;
472
473                         APP_CHECK(parse_range(tokens[ti], &port_low,
474                                 &port_high) == 0, status, "unrecognized "
475                                 "input \"%s\", expect \"port_from:"
476                                 "port_to\"", tokens[ti]);
477                         if (status->status < 0)
478                                 return;
479
480                         rule_ipv6->field[10].value.u16 = port_low;
481                         rule_ipv6->field[10].mask_range.u16 = port_high;
482
483                         dport_p = 1;
484                         continue;
485                 }
486
487                 /* unrecognizeable input */
488                 APP_CHECK(0, status, "unrecognized input \"%s\"",
489                         tokens[ti]);
490                 return;
491         }
492
493         /* check if argument(s) are missing */
494         APP_CHECK(esp_p == 1, status, "missing argument \"esp\"");
495         if (status->status < 0)
496                 return;
497
498         APP_CHECK(protect_p | bypass_p | discard_p, status, "missing "
499                 "argument \"protect\", \"bypass\", or \"discard\"");
500         if (status->status < 0)
501                 return;
502
503         *ri = *ri + 1;
504 }
505
506 static inline void
507 print_one_ip6_rule(const struct acl6_rules *rule, int32_t extra)
508 {
509         uint8_t a, b, c, d;
510
511         uint32_t_to_char(rule->field[IP6_SRC0].value.u32,
512                 &a, &b, &c, &d);
513         printf("%.2x%.2x:%.2x%.2x", a, b, c, d);
514         uint32_t_to_char(rule->field[IP6_SRC1].value.u32,
515                 &a, &b, &c, &d);
516         printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
517         uint32_t_to_char(rule->field[IP6_SRC2].value.u32,
518                 &a, &b, &c, &d);
519         printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
520         uint32_t_to_char(rule->field[IP6_SRC3].value.u32,
521                 &a, &b, &c, &d);
522         printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d,
523                         rule->field[IP6_SRC0].mask_range.u32
524                         + rule->field[IP6_SRC1].mask_range.u32
525                         + rule->field[IP6_SRC2].mask_range.u32
526                         + rule->field[IP6_SRC3].mask_range.u32);
527
528         uint32_t_to_char(rule->field[IP6_DST0].value.u32,
529                 &a, &b, &c, &d);
530         printf("%.2x%.2x:%.2x%.2x", a, b, c, d);
531         uint32_t_to_char(rule->field[IP6_DST1].value.u32,
532                 &a, &b, &c, &d);
533         printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
534         uint32_t_to_char(rule->field[IP6_DST2].value.u32,
535                 &a, &b, &c, &d);
536         printf(":%.2x%.2x:%.2x%.2x", a, b, c, d);
537         uint32_t_to_char(rule->field[IP6_DST3].value.u32,
538                 &a, &b, &c, &d);
539         printf(":%.2x%.2x:%.2x%.2x/%u ", a, b, c, d,
540                         rule->field[IP6_DST0].mask_range.u32
541                         + rule->field[IP6_DST1].mask_range.u32
542                         + rule->field[IP6_DST2].mask_range.u32
543                         + rule->field[IP6_DST3].mask_range.u32);
544
545         printf("%hu : %hu %hu : %hu 0x%hhx/0x%hhx ",
546                 rule->field[IP6_SRCP].value.u16,
547                 rule->field[IP6_SRCP].mask_range.u16,
548                 rule->field[IP6_DSTP].value.u16,
549                 rule->field[IP6_DSTP].mask_range.u16,
550                 rule->field[IP6_PROTO].value.u8,
551                 rule->field[IP6_PROTO].mask_range.u8);
552         if (extra)
553                 printf("0x%x-0x%x-0x%x ",
554                         rule->data.category_mask,
555                         rule->data.priority,
556                         rule->data.userdata);
557 }
558
559 static inline void
560 dump_ip6_rules(const struct acl6_rules *rule, int32_t num, int32_t extra)
561 {
562         int32_t i;
563
564         for (i = 0; i < num; i++, rule++) {
565                 printf("\t%d:", i + 1);
566                 print_one_ip6_rule(rule, extra);
567                 printf("\n");
568         }
569 }
570
571 static struct rte_acl_ctx *
572 acl6_init(const char *name, int32_t socketid, const struct acl6_rules *rules,
573                 uint32_t rules_nb)
574 {
575         char s[PATH_MAX];
576         struct rte_acl_param acl_param;
577         struct rte_acl_config acl_build_param;
578         struct rte_acl_ctx *ctx;
579
580         printf("Creating SP context with %u max rules\n", MAX_ACL_RULE_NUM);
581
582         memset(&acl_param, 0, sizeof(acl_param));
583
584         /* Create ACL contexts */
585         snprintf(s, sizeof(s), "%s_%d", name, socketid);
586
587         printf("IPv4 %s entries [%u]:\n", s, rules_nb);
588         dump_ip6_rules(rules, rules_nb, 1);
589
590         acl_param.name = s;
591         acl_param.socket_id = socketid;
592         acl_param.rule_size = RTE_ACL_RULE_SZ(RTE_DIM(ip6_defs));
593         acl_param.max_rule_num = MAX_ACL_RULE_NUM;
594
595         ctx = rte_acl_create(&acl_param);
596         if (ctx == NULL)
597                 rte_exit(EXIT_FAILURE, "Failed to create ACL context\n");
598
599         if (rte_acl_add_rules(ctx, (const struct rte_acl_rule *)rules,
600                                 rules_nb) < 0)
601                 rte_exit(EXIT_FAILURE, "add rules failed\n");
602
603         /* Perform builds */
604         memset(&acl_build_param, 0, sizeof(acl_build_param));
605
606         acl_build_param.num_categories = DEFAULT_MAX_CATEGORIES;
607         acl_build_param.num_fields = RTE_DIM(ip6_defs);
608         memcpy(&acl_build_param.defs, ip6_defs, sizeof(ip6_defs));
609
610         if (rte_acl_build(ctx, &acl_build_param) != 0)
611                 rte_exit(EXIT_FAILURE, "Failed to build ACL trie\n");
612
613         rte_acl_dump(ctx);
614
615         return ctx;
616 }
617
618 void
619 sp6_init(struct socket_ctx *ctx, int32_t socket_id)
620 {
621         const char *name;
622
623         if (ctx == NULL)
624                 rte_exit(EXIT_FAILURE, "NULL context.\n");
625
626         if (ctx->sp_ip6_in != NULL)
627                 rte_exit(EXIT_FAILURE, "Inbound IPv6 SP DB for socket %u "
628                                 "already initialized\n", socket_id);
629
630         if (ctx->sp_ip6_out != NULL)
631                 rte_exit(EXIT_FAILURE, "Outbound IPv6 SP DB for socket %u "
632                                 "already initialized\n", socket_id);
633
634         if (nb_acl6_rules_in > 0) {
635                 name = "sp_ip6_in";
636                 ctx->sp_ip6_in = (struct sp_ctx *)acl6_init(name,
637                         socket_id, acl6_rules_in, nb_acl6_rules_in);
638         } else
639                 RTE_LOG(WARNING, IPSEC, "No IPv6 SP Inbound rule "
640                         "specified\n");
641
642         if (nb_acl6_rules_out > 0) {
643                 name = "sp_ip6_out";
644                 ctx->sp_ip6_out = (struct sp_ctx *)acl6_init(name,
645                         socket_id, acl6_rules_out, nb_acl6_rules_out);
646         } else
647                 RTE_LOG(WARNING, IPSEC, "No IPv6 SP Outbound rule "
648                         "specified\n");
649 }