examples/ipsec-secgw: implement inbound SAD
[dpdk.git] / examples / ipsec-secgw / sad.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Intel Corporation
3  */
4
5 #include <rte_errno.h>
6
7 #include "ipsec.h"
8 #include "sad.h"
9
10 int
11 ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
12 {
13         int ret;
14         void *tmp = NULL;
15         union rte_ipsec_sad_key key = { {0} };
16         const union rte_ipsec_sad_key *lookup_key[1];
17
18         /* spi field is common for ipv4 and ipv6 key types */
19         key.v4.spi = rte_cpu_to_be_32(sa->spi);
20         lookup_key[0] = &key;
21         switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
22         case IP4_TUNNEL:
23                 rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
24                 if (tmp != NULL)
25                         return -EEXIST;
26
27                 ret = rte_ipsec_sad_add(sad->sad_v4, &key,
28                         RTE_IPSEC_SAD_SPI_ONLY, sa);
29                 if (ret != 0)
30                         return ret;
31                 break;
32         case IP6_TUNNEL:
33                 rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
34                 if (tmp != NULL)
35                         return -EEXIST;
36
37                 ret = rte_ipsec_sad_add(sad->sad_v6, &key,
38                         RTE_IPSEC_SAD_SPI_ONLY, sa);
39                 if (ret != 0)
40                         return ret;
41                 break;
42         case TRANSPORT:
43                 if (sp4_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
44                         rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
45                         if (tmp != NULL)
46                                 return -EEXIST;
47
48                         ret = rte_ipsec_sad_add(sad->sad_v4, &key,
49                                 RTE_IPSEC_SAD_SPI_ONLY, sa);
50                         if (ret != 0)
51                                 return ret;
52                 }
53                 if (sp6_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
54                         rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
55                         if (tmp != NULL)
56                                 return -EEXIST;
57
58                         ret = rte_ipsec_sad_add(sad->sad_v6, &key,
59                                 RTE_IPSEC_SAD_SPI_ONLY, sa);
60                         if (ret != 0)
61                                 return ret;
62                 }
63         }
64
65         return 0;
66 }
67
68 int
69 ipsec_sad_create(const char *name, struct ipsec_sad *sad,
70         int socket_id, struct ipsec_sa_cnt *sa_cnt)
71 {
72         int ret;
73         struct rte_ipsec_sad_conf sad_conf;
74         char sad_name[RTE_IPSEC_SAD_NAMESIZE];
75
76         if ((name == NULL) || (sad == NULL) || (sa_cnt == NULL))
77                 return -EINVAL;
78
79         ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v4", name);
80         if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
81                 return -ENAMETOOLONG;
82
83         sad_conf.socket_id = socket_id;
84         sad_conf.flags = 0;
85         /* Make SAD have extra 25% of required number of entries */
86         sad_conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = sa_cnt->nb_v4 * 5 / 4;
87         sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
88         sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
89
90         if (sa_cnt->nb_v4 != 0) {
91                 sad->sad_v4 = rte_ipsec_sad_create(sad_name, &sad_conf);
92                 if (sad->sad_v4 == NULL)
93                         return -rte_errno;
94         }
95
96         ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v6", name);
97         if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
98                 return -ENAMETOOLONG;
99         sad_conf.flags = RTE_IPSEC_SAD_FLAG_IPV6;
100         sad_conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = sa_cnt->nb_v6 * 5 / 4;
101
102         if (sa_cnt->nb_v6 != 0) {
103                 sad->sad_v6 = rte_ipsec_sad_create(name, &sad_conf);
104                 if (sad->sad_v6 == NULL)
105                         return -rte_errno;
106         }
107
108         return 0;
109 }