1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2019 Intel Corporation
*/
#include <rte_errno.h>
#include <rte_malloc.h>
#include "ipsec.h"
#include "sad.h"
RTE_DEFINE_PER_LCORE(struct ipsec_sad_cache, sad_cache) = {
.v4 = NULL,
.v6 = NULL,
.mask = 0,
};
int
ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
{
int ret;
void *tmp = NULL;
union rte_ipsec_sad_key key = { {0} };
const union rte_ipsec_sad_key *lookup_key[1];
/* spi field is common for ipv4 and ipv6 key types */
key.v4.spi = rte_cpu_to_be_32(sa->spi);
lookup_key[0] = &key;
switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
case IP4_TUNNEL:
rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
if (tmp != NULL)
return -EEXIST;
ret = rte_ipsec_sad_add(sad->sad_v4, &key,
RTE_IPSEC_SAD_SPI_ONLY, sa);
if (ret != 0)
return ret;
break;
case IP6_TUNNEL:
rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
if (tmp != NULL)
return -EEXIST;
ret = rte_ipsec_sad_add(sad->sad_v6, &key,
RTE_IPSEC_SAD_SPI_ONLY, sa);
if (ret != 0)
return ret;
break;
case TRANSPORT:
if (sp4_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
if (tmp != NULL)
return -EEXIST;
ret = rte_ipsec_sad_add(sad->sad_v4, &key,
RTE_IPSEC_SAD_SPI_ONLY, sa);
if (ret != 0)
return ret;
}
if (sp6_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
if (tmp != NULL)
return -EEXIST;
ret = rte_ipsec_sad_add(sad->sad_v6, &key,
RTE_IPSEC_SAD_SPI_ONLY, sa);
if (ret != 0)
return ret;
}
}
return 0;
}
/*
* Init per lcore SAD cache.
* Must be called by every processing lcore.
*/
int
ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent)
{
uint32_t cache_elem;
size_t cache_mem_sz;
struct ipsec_sad_cache *cache;
cache = &RTE_PER_LCORE(sad_cache);
cache_elem = rte_align32pow2(nb_cache_ent);
cache_mem_sz = sizeof(struct ipsec_sa *) * cache_elem;
if (cache_mem_sz != 0) {
cache->v4 = rte_zmalloc_socket(NULL, cache_mem_sz,
RTE_CACHE_LINE_SIZE, rte_socket_id());
if (cache->v4 == NULL)
return -rte_errno;
cache->v6 = rte_zmalloc_socket(NULL, cache_mem_sz,
RTE_CACHE_LINE_SIZE, rte_socket_id());
if (cache->v6 == NULL)
return -rte_errno;
cache->mask = cache_elem - 1;
}
return 0;
}
int
ipsec_sad_create(const char *name, struct ipsec_sad *sad,
int socket_id, struct ipsec_sa_cnt *sa_cnt)
{
int ret;
struct rte_ipsec_sad_conf sad_conf;
char sad_name[RTE_IPSEC_SAD_NAMESIZE];
if ((name == NULL) || (sad == NULL) || (sa_cnt == NULL))
return -EINVAL;
ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v4", name);
if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
return -ENAMETOOLONG;
sad_conf.socket_id = socket_id;
sad_conf.flags = 0;
/* Make SAD have extra 25% of required number of entries */
sad_conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = sa_cnt->nb_v4 * 5 / 4;
sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
if (sa_cnt->nb_v4 != 0) {
sad->sad_v4 = rte_ipsec_sad_create(sad_name, &sad_conf);
if (sad->sad_v4 == NULL)
return -rte_errno;
}
ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v6", name);
if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
return -ENAMETOOLONG;
sad_conf.flags = RTE_IPSEC_SAD_FLAG_IPV6;
sad_conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = sa_cnt->nb_v6 * 5 / 4;
if (sa_cnt->nb_v6 != 0) {
sad->sad_v6 = rte_ipsec_sad_create(name, &sad_conf);
if (sad->sad_v6 == NULL)
return -rte_errno;
}
return 0;
}
|