From 8e499dff73fdf18281bf8ff4112712bdfc1da76d Mon Sep 17 00:00:00 2001 From: Vladimir Medvedkin Date: Fri, 31 Jan 2020 17:39:39 +0000 Subject: [PATCH] examples/ipsec-secgw: implement inbound SAD Add initial support for librte_ipsec SAD library Signed-off-by: Vladimir Medvedkin Acked-by: Konstantin Ananyev Acked-by: Akhil Goyal Acked-by: Anoob Joseph --- examples/ipsec-secgw/ipsec.h | 7 +++ examples/ipsec-secgw/sad.c | 109 +++++++++++++++++++++++++++++++++++ examples/ipsec-secgw/sad.h | 75 ++++++++++++++++++++++++ 3 files changed, 191 insertions(+) create mode 100644 examples/ipsec-secgw/sad.c create mode 100644 examples/ipsec-secgw/sad.h diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h index 8e075216c3..9ddb5d91b2 100644 --- a/examples/ipsec-secgw/ipsec.h +++ b/examples/ipsec-secgw/ipsec.h @@ -53,6 +53,13 @@ struct ipsec_xform; struct rte_mbuf; struct ipsec_sa; +/* + * Keeps number of configured SA's for each address family: + */ +struct ipsec_sa_cnt { + uint32_t nb_v4; + uint32_t nb_v6; +}; typedef int32_t (*ipsec_xform_fn)(struct rte_mbuf *m, struct ipsec_sa *sa, struct rte_crypto_op *cop); diff --git a/examples/ipsec-secgw/sad.c b/examples/ipsec-secgw/sad.c new file mode 100644 index 0000000000..fd31101c30 --- /dev/null +++ b/examples/ipsec-secgw/sad.c @@ -0,0 +1,109 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include + +#include "ipsec.h" +#include "sad.h" + +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; +} + +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; +} diff --git a/examples/ipsec-secgw/sad.h b/examples/ipsec-secgw/sad.h new file mode 100644 index 0000000000..29ed0f873d --- /dev/null +++ b/examples/ipsec-secgw/sad.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#ifndef __SAD_H__ +#define __SAD_H__ + +#include + +struct ipsec_sad { + struct rte_ipsec_sad *sad_v4; + struct rte_ipsec_sad *sad_v6; +}; + +int ipsec_sad_create(const char *name, struct ipsec_sad *sad, + int socket_id, struct ipsec_sa_cnt *sa_cnt); + +int ipsec_sad_add(struct ipsec_sad *sad, struct ipsec_sa *sa); + +static inline void +sad_lookup(const struct ipsec_sad *sad, struct rte_mbuf *pkts[], + void *sa[], uint16_t nb_pkts) +{ + uint32_t i; + uint32_t nb_v4 = 0, nb_v6 = 0; + struct rte_esp_hdr *esp; + struct rte_ipv4_hdr *ipv4; + struct rte_ipv6_hdr *ipv6; + struct rte_ipsec_sadv4_key v4[nb_pkts]; + struct rte_ipsec_sadv6_key v6[nb_pkts]; + int v4_idxes[nb_pkts]; + int v6_idxes[nb_pkts]; + const union rte_ipsec_sad_key *keys_v4[nb_pkts]; + const union rte_ipsec_sad_key *keys_v6[nb_pkts]; + void *v4_res[nb_pkts]; + void *v6_res[nb_pkts]; + + /* split received packets by address family into two arrays */ + for (i = 0; i < nb_pkts; i++) { + ipv4 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv4_hdr *); + esp = rte_pktmbuf_mtod_offset(pkts[i], struct rte_esp_hdr *, + pkts[i]->l3_len); + if ((ipv4->version_ihl >> 4) == IPVERSION) { + v4[nb_v4].spi = esp->spi; + v4[nb_v4].dip = ipv4->dst_addr; + v4[nb_v4].sip = ipv4->src_addr; + keys_v4[nb_v4] = (const union rte_ipsec_sad_key *) + &v4[nb_v4]; + v4_idxes[nb_v4++] = i; + } else { + ipv6 = rte_pktmbuf_mtod(pkts[i], struct rte_ipv6_hdr *); + v6[nb_v6].spi = esp->spi; + memcpy(v6[nb_v6].dip, ipv6->dst_addr, + sizeof(ipv6->dst_addr)); + memcpy(v6[nb_v6].sip, ipv6->src_addr, + sizeof(ipv6->src_addr)); + keys_v6[nb_v6] = (const union rte_ipsec_sad_key *) + &v6[nb_v6]; + v6_idxes[nb_v6++] = i; + } + } + + if (nb_v4 != 0) + rte_ipsec_sad_lookup(sad->sad_v4, keys_v4, v4_res, nb_v4); + if (nb_v6 != 0) + rte_ipsec_sad_lookup(sad->sad_v6, keys_v6, v6_res, nb_v6); + + for (i = 0; i < nb_v4; i++) + sa[v4_idxes[i]] = v4_res[i]; + + for (i = 0; i < nb_v6; i++) + sa[v6_idxes[i]] = v6_res[i]; +} + +#endif /* __SAD_H__ */ -- 2.20.1