New upstream version 18.11.2
[deb_dpdk.git] / examples / ipsec-secgw / sp6.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016 Intel Corporation
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
37 static struct rte_acl_field_def ip6_defs[IP6_NUM] = {
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
119 static struct acl6_rules acl6_rules_out[MAX_ACL_RULE_NUM];
120 static uint32_t nb_acl6_rules_out;
121
122 static struct acl6_rules acl6_rules_in[MAX_ACL_RULE_NUM];
123 static uint32_t nb_acl6_rules_in;
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 */
133         uint32_t tv;
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
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;
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
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
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
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
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 }