18e499dffSVladimir Medvedkin /* SPDX-License-Identifier: BSD-3-Clause
28e499dffSVladimir Medvedkin * Copyright(c) 2019 Intel Corporation
38e499dffSVladimir Medvedkin */
48e499dffSVladimir Medvedkin
58e499dffSVladimir Medvedkin #include <rte_errno.h>
6*2cf67788SVladimir Medvedkin #include <rte_malloc.h>
78e499dffSVladimir Medvedkin
88e499dffSVladimir Medvedkin #include "ipsec.h"
98e499dffSVladimir Medvedkin #include "sad.h"
108e499dffSVladimir Medvedkin
11*2cf67788SVladimir Medvedkin RTE_DEFINE_PER_LCORE(struct ipsec_sad_cache, sad_cache) = {
12*2cf67788SVladimir Medvedkin .v4 = NULL,
13*2cf67788SVladimir Medvedkin .v6 = NULL,
14*2cf67788SVladimir Medvedkin .mask = 0,
15*2cf67788SVladimir Medvedkin };
16*2cf67788SVladimir Medvedkin
178e499dffSVladimir Medvedkin int
ipsec_sad_add(struct ipsec_sad * sad,struct ipsec_sa * sa)188e499dffSVladimir Medvedkin ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa)
198e499dffSVladimir Medvedkin {
208e499dffSVladimir Medvedkin int ret;
218e499dffSVladimir Medvedkin void *tmp = NULL;
228e499dffSVladimir Medvedkin union rte_ipsec_sad_key key = { {0} };
238e499dffSVladimir Medvedkin const union rte_ipsec_sad_key *lookup_key[1];
248e499dffSVladimir Medvedkin
258e499dffSVladimir Medvedkin /* spi field is common for ipv4 and ipv6 key types */
268e499dffSVladimir Medvedkin key.v4.spi = rte_cpu_to_be_32(sa->spi);
278e499dffSVladimir Medvedkin lookup_key[0] = &key;
288e499dffSVladimir Medvedkin switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
298e499dffSVladimir Medvedkin case IP4_TUNNEL:
308e499dffSVladimir Medvedkin rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
318e499dffSVladimir Medvedkin if (tmp != NULL)
328e499dffSVladimir Medvedkin return -EEXIST;
338e499dffSVladimir Medvedkin
348e499dffSVladimir Medvedkin ret = rte_ipsec_sad_add(sad->sad_v4, &key,
358e499dffSVladimir Medvedkin RTE_IPSEC_SAD_SPI_ONLY, sa);
368e499dffSVladimir Medvedkin if (ret != 0)
378e499dffSVladimir Medvedkin return ret;
388e499dffSVladimir Medvedkin break;
398e499dffSVladimir Medvedkin case IP6_TUNNEL:
408e499dffSVladimir Medvedkin rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
418e499dffSVladimir Medvedkin if (tmp != NULL)
428e499dffSVladimir Medvedkin return -EEXIST;
438e499dffSVladimir Medvedkin
448e499dffSVladimir Medvedkin ret = rte_ipsec_sad_add(sad->sad_v6, &key,
458e499dffSVladimir Medvedkin RTE_IPSEC_SAD_SPI_ONLY, sa);
468e499dffSVladimir Medvedkin if (ret != 0)
478e499dffSVladimir Medvedkin return ret;
488e499dffSVladimir Medvedkin break;
498e499dffSVladimir Medvedkin case TRANSPORT:
508e499dffSVladimir Medvedkin if (sp4_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
518e499dffSVladimir Medvedkin rte_ipsec_sad_lookup(sad->sad_v4, lookup_key, &tmp, 1);
528e499dffSVladimir Medvedkin if (tmp != NULL)
538e499dffSVladimir Medvedkin return -EEXIST;
548e499dffSVladimir Medvedkin
558e499dffSVladimir Medvedkin ret = rte_ipsec_sad_add(sad->sad_v4, &key,
568e499dffSVladimir Medvedkin RTE_IPSEC_SAD_SPI_ONLY, sa);
578e499dffSVladimir Medvedkin if (ret != 0)
588e499dffSVladimir Medvedkin return ret;
598e499dffSVladimir Medvedkin }
608e499dffSVladimir Medvedkin if (sp6_spi_present(sa->spi, 1, NULL, NULL) >= 0) {
618e499dffSVladimir Medvedkin rte_ipsec_sad_lookup(sad->sad_v6, lookup_key, &tmp, 1);
628e499dffSVladimir Medvedkin if (tmp != NULL)
638e499dffSVladimir Medvedkin return -EEXIST;
648e499dffSVladimir Medvedkin
658e499dffSVladimir Medvedkin ret = rte_ipsec_sad_add(sad->sad_v6, &key,
668e499dffSVladimir Medvedkin RTE_IPSEC_SAD_SPI_ONLY, sa);
678e499dffSVladimir Medvedkin if (ret != 0)
688e499dffSVladimir Medvedkin return ret;
698e499dffSVladimir Medvedkin }
708e499dffSVladimir Medvedkin }
718e499dffSVladimir Medvedkin
728e499dffSVladimir Medvedkin return 0;
738e499dffSVladimir Medvedkin }
748e499dffSVladimir Medvedkin
75*2cf67788SVladimir Medvedkin /*
76*2cf67788SVladimir Medvedkin * Init per lcore SAD cache.
77*2cf67788SVladimir Medvedkin * Must be called by every processing lcore.
78*2cf67788SVladimir Medvedkin */
79*2cf67788SVladimir Medvedkin int
ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent)80*2cf67788SVladimir Medvedkin ipsec_sad_lcore_cache_init(uint32_t nb_cache_ent)
81*2cf67788SVladimir Medvedkin {
82*2cf67788SVladimir Medvedkin uint32_t cache_elem;
83*2cf67788SVladimir Medvedkin size_t cache_mem_sz;
84*2cf67788SVladimir Medvedkin struct ipsec_sad_cache *cache;
85*2cf67788SVladimir Medvedkin
86*2cf67788SVladimir Medvedkin cache = &RTE_PER_LCORE(sad_cache);
87*2cf67788SVladimir Medvedkin
88*2cf67788SVladimir Medvedkin cache_elem = rte_align32pow2(nb_cache_ent);
89*2cf67788SVladimir Medvedkin cache_mem_sz = sizeof(struct ipsec_sa *) * cache_elem;
90*2cf67788SVladimir Medvedkin
91*2cf67788SVladimir Medvedkin if (cache_mem_sz != 0) {
92*2cf67788SVladimir Medvedkin cache->v4 = rte_zmalloc_socket(NULL, cache_mem_sz,
93*2cf67788SVladimir Medvedkin RTE_CACHE_LINE_SIZE, rte_socket_id());
94*2cf67788SVladimir Medvedkin if (cache->v4 == NULL)
95*2cf67788SVladimir Medvedkin return -rte_errno;
96*2cf67788SVladimir Medvedkin
97*2cf67788SVladimir Medvedkin cache->v6 = rte_zmalloc_socket(NULL, cache_mem_sz,
98*2cf67788SVladimir Medvedkin RTE_CACHE_LINE_SIZE, rte_socket_id());
99*2cf67788SVladimir Medvedkin if (cache->v6 == NULL)
100*2cf67788SVladimir Medvedkin return -rte_errno;
101*2cf67788SVladimir Medvedkin
102*2cf67788SVladimir Medvedkin cache->mask = cache_elem - 1;
103*2cf67788SVladimir Medvedkin }
104*2cf67788SVladimir Medvedkin
105*2cf67788SVladimir Medvedkin return 0;
106*2cf67788SVladimir Medvedkin }
107*2cf67788SVladimir Medvedkin
1088e499dffSVladimir Medvedkin int
ipsec_sad_create(const char * name,struct ipsec_sad * sad,int socket_id,struct ipsec_sa_cnt * sa_cnt)1098e499dffSVladimir Medvedkin ipsec_sad_create(const char *name, struct ipsec_sad *sad,
1108e499dffSVladimir Medvedkin int socket_id, struct ipsec_sa_cnt *sa_cnt)
1118e499dffSVladimir Medvedkin {
1128e499dffSVladimir Medvedkin int ret;
1138e499dffSVladimir Medvedkin struct rte_ipsec_sad_conf sad_conf;
1148e499dffSVladimir Medvedkin char sad_name[RTE_IPSEC_SAD_NAMESIZE];
1158e499dffSVladimir Medvedkin
1168e499dffSVladimir Medvedkin if ((name == NULL) || (sad == NULL) || (sa_cnt == NULL))
1178e499dffSVladimir Medvedkin return -EINVAL;
1188e499dffSVladimir Medvedkin
1198e499dffSVladimir Medvedkin ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v4", name);
1208e499dffSVladimir Medvedkin if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
1218e499dffSVladimir Medvedkin return -ENAMETOOLONG;
1228e499dffSVladimir Medvedkin
1238e499dffSVladimir Medvedkin sad_conf.socket_id = socket_id;
1248e499dffSVladimir Medvedkin sad_conf.flags = 0;
1258e499dffSVladimir Medvedkin /* Make SAD have extra 25% of required number of entries */
1268e499dffSVladimir Medvedkin sad_conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = sa_cnt->nb_v4 * 5 / 4;
1278e499dffSVladimir Medvedkin sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP] = 0;
1288e499dffSVladimir Medvedkin sad_conf.max_sa[RTE_IPSEC_SAD_SPI_DIP_SIP] = 0;
1298e499dffSVladimir Medvedkin
1308e499dffSVladimir Medvedkin if (sa_cnt->nb_v4 != 0) {
1318e499dffSVladimir Medvedkin sad->sad_v4 = rte_ipsec_sad_create(sad_name, &sad_conf);
1328e499dffSVladimir Medvedkin if (sad->sad_v4 == NULL)
1338e499dffSVladimir Medvedkin return -rte_errno;
1348e499dffSVladimir Medvedkin }
1358e499dffSVladimir Medvedkin
1368e499dffSVladimir Medvedkin ret = snprintf(sad_name, RTE_IPSEC_SAD_NAMESIZE, "%s_v6", name);
1378e499dffSVladimir Medvedkin if (ret < 0 || ret >= RTE_IPSEC_SAD_NAMESIZE)
1388e499dffSVladimir Medvedkin return -ENAMETOOLONG;
1398e499dffSVladimir Medvedkin sad_conf.flags = RTE_IPSEC_SAD_FLAG_IPV6;
1408e499dffSVladimir Medvedkin sad_conf.max_sa[RTE_IPSEC_SAD_SPI_ONLY] = sa_cnt->nb_v6 * 5 / 4;
1418e499dffSVladimir Medvedkin
1428e499dffSVladimir Medvedkin if (sa_cnt->nb_v6 != 0) {
1438e499dffSVladimir Medvedkin sad->sad_v6 = rte_ipsec_sad_create(name, &sad_conf);
1448e499dffSVladimir Medvedkin if (sad->sad_v6 == NULL)
1458e499dffSVladimir Medvedkin return -rte_errno;
1468e499dffSVladimir Medvedkin }
1478e499dffSVladimir Medvedkin
1488e499dffSVladimir Medvedkin return 0;
1498e499dffSVladimir Medvedkin }
150