From: Vladimir Medvedkin Date: Mon, 21 Oct 2019 14:35:42 +0000 (+0100) Subject: ipsec: add inbound SAD API X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=401633d9c112;p=dpdk.git ipsec: add inbound SAD API According to RFC 4301 IPSec implementation needs an inbound SA database (SAD). For each incoming inbound IPSec-protected packet (ESP or AH) it has to perform a lookup within it's SAD. Lookup should be performed by: Security Parameters Index (SPI) + destination IP (DIP) + source IP (SIP) or SPI + DIP or SPI only and an implementation has to return the 'longest' existing match. This patch extend DPDK IPsec library with inbound security association database (SAD) API implementation that: - conforms to the RFC requirements above - can scale up to millions of entries - supports fast lookups - supports incremental updates Signed-off-by: Vladimir Medvedkin Acked-by: Akhil Goyal Acked-by: Konstantin Ananyev --- diff --git a/doc/guides/prog_guide/ipsec_lib.rst b/doc/guides/prog_guide/ipsec_lib.rst index 17d9da28fb..6900651bd6 100644 --- a/doc/guides/prog_guide/ipsec_lib.rst +++ b/doc/guides/prog_guide/ipsec_lib.rst @@ -143,6 +143,21 @@ In that mode the library functions perform To accommodate future custom implementations function pointers model is used for both *crypto_prepare* and *process* implementations. +SA database API +---------------- + +SA database(SAD) is a table with pairs. + +Value is an opaque user provided pointer to the user defined SA data structure. + +According to RFC4301 each SA can be uniquely identified by a key +which is either: + + - security parameter index(SPI) + - or SPI and destination IP(DIP) + - or SPI, DIP and source IP(SIP) + +In case of multiple matches, longest matching key will be returned. Supported features ------------------ diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index fc9da16b2b..a00938b7c7 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -136,6 +136,10 @@ New Features and use memory zones as external buffers instead of keeping the data directly in mbuf areas. +* **Updated the IPSec library.** + + Added SA Database API to ``librte_ipsec``. + * **Introduced FIFO for NTB PMD.** Introduced FIFO for NTB (Non-transparent Bridge) PMD to support diff --git a/lib/librte_ipsec/Makefile b/lib/librte_ipsec/Makefile index 22f29d98a8..5aaab72cb4 100644 --- a/lib/librte_ipsec/Makefile +++ b/lib/librte_ipsec/Makefile @@ -21,10 +21,12 @@ SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += esp_inb.c SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += esp_outb.c SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += sa.c SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += ses.c +SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += ipsec_sad.c # install header files SYMLINK-$(CONFIG_RTE_LIBRTE_IPSEC)-include += rte_ipsec.h SYMLINK-$(CONFIG_RTE_LIBRTE_IPSEC)-include += rte_ipsec_group.h SYMLINK-$(CONFIG_RTE_LIBRTE_IPSEC)-include += rte_ipsec_sa.h +SYMLINK-$(CONFIG_RTE_LIBRTE_IPSEC)-include += rte_ipsec_sad.h include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_ipsec/ipsec_sad.c b/lib/librte_ipsec/ipsec_sad.c new file mode 100644 index 0000000000..703be654f5 --- /dev/null +++ b/lib/librte_ipsec/ipsec_sad.c @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include + +#include "rte_ipsec_sad.h" + +int +rte_ipsec_sad_add(__rte_unused struct rte_ipsec_sad *sad, + __rte_unused const union rte_ipsec_sad_key *key, + __rte_unused int key_type, __rte_unused void *sa) +{ + return -ENOTSUP; +} + +int +rte_ipsec_sad_del(__rte_unused struct rte_ipsec_sad *sad, + __rte_unused const union rte_ipsec_sad_key *key, + __rte_unused int key_type) +{ + return -ENOTSUP; +} + +struct rte_ipsec_sad * +rte_ipsec_sad_create(__rte_unused const char *name, + __rte_unused const struct rte_ipsec_sad_conf *conf) +{ + return NULL; +} + +struct rte_ipsec_sad * +rte_ipsec_sad_find_existing(__rte_unused const char *name) +{ + return NULL; +} + +void +rte_ipsec_sad_destroy(__rte_unused struct rte_ipsec_sad *sad) +{ + return; +} + +int +rte_ipsec_sad_lookup(__rte_unused const struct rte_ipsec_sad *sad, + __rte_unused const union rte_ipsec_sad_key *keys[], + __rte_unused void *sa[], __rte_unused uint32_t n) +{ + return -ENOTSUP; +} diff --git a/lib/librte_ipsec/meson.build b/lib/librte_ipsec/meson.build index 7ea0c7dbb2..91b98674d4 100644 --- a/lib/librte_ipsec/meson.build +++ b/lib/librte_ipsec/meson.build @@ -3,8 +3,8 @@ allow_experimental_apis = true -sources = files('esp_inb.c', 'esp_outb.c', 'sa.c', 'ses.c') +sources = files('esp_inb.c', 'esp_outb.c', 'sa.c', 'ses.c', 'ipsec_sad.c') -headers = files('rte_ipsec.h', 'rte_ipsec_group.h', 'rte_ipsec_sa.h') +headers = files('rte_ipsec.h', 'rte_ipsec_group.h', 'rte_ipsec_sa.h', 'rte_ipsec_sad.h') deps += ['mbuf', 'net', 'cryptodev', 'security'] diff --git a/lib/librte_ipsec/rte_ipsec_sad.h b/lib/librte_ipsec/rte_ipsec_sad.h new file mode 100644 index 0000000000..8386f73df7 --- /dev/null +++ b/lib/librte_ipsec/rte_ipsec_sad.h @@ -0,0 +1,176 @@ + +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#ifndef _RTE_IPSEC_SAD_H_ +#define _RTE_IPSEC_SAD_H_ + +#include + +/** + * @file rte_ipsec_sad.h + * @b EXPERIMENTAL: this API may change without prior notice + * + * RTE IPsec security association database (SAD) support. + * Contains helper functions to lookup and maintain SAD + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct rte_ipsec_sad; + +/** Type of key */ +enum { + RTE_IPSEC_SAD_SPI_ONLY = 0, + RTE_IPSEC_SAD_SPI_DIP, + RTE_IPSEC_SAD_SPI_DIP_SIP, + RTE_IPSEC_SAD_KEY_TYPE_MASK, +}; + +struct rte_ipsec_sadv4_key { + uint32_t spi; + uint32_t dip; + uint32_t sip; +}; + +struct rte_ipsec_sadv6_key { + uint32_t spi; + uint8_t dip[16]; + uint8_t sip[16]; +}; + +union rte_ipsec_sad_key { + struct rte_ipsec_sadv4_key v4; + struct rte_ipsec_sadv6_key v6; +}; + +/** Flag to create SAD with ipv6 dip and sip addresses */ +#define RTE_IPSEC_SAD_FLAG_IPV6 0x1 +/** Flag to support reader writer concurrency */ +#define RTE_IPSEC_SAD_FLAG_RW_CONCURRENCY 0x2 + +/** IPsec SAD configuration structure */ +struct rte_ipsec_sad_conf { + /** CPU socket ID where rte_ipsec_sad should be allocated */ + int socket_id; + /** maximum number of SA for each type of key */ + uint32_t max_sa[RTE_IPSEC_SAD_KEY_TYPE_MASK]; + /** RTE_IPSEC_SAD_FLAG_* flags */ + uint32_t flags; +}; + +/** + * Add a rule into the SAD. Could be safely called with concurrent lookups + * if RTE_IPSEC_SAD_FLAG_RW_CONCURRENCY flag was configured on creation time. + * While with this flag multi-reader - one-writer model Is MT safe, + * multi-writer model is not and required extra synchronisation. + * + * @param sad + * SAD object handle + * @param key + * pointer to the key + * @param key_type + * key type (spi only/spi+dip/spi+dip+sip) + * @param sa + * Pointer associated with the key to save in a SAD + * Must be 4 bytes aligned. + * @return + * 0 on success, negative value otherwise + */ +__rte_experimental +int +rte_ipsec_sad_add(struct rte_ipsec_sad *sad, + const union rte_ipsec_sad_key *key, + int key_type, void *sa); + +/** + * Delete a rule from the SAD. Could be safely called with concurrent lookups + * if RTE_IPSEC_SAD_FLAG_RW_CONCURRENCY flag was configured on creation time. + * While with this flag multi-reader - one-writer model Is MT safe, + * multi-writer model is not and required extra synchronisation. + * + * @param sad + * SAD object handle + * @param key + * pointer to the key + * @param key_type + * key type (spi only/spi+dip/spi+dip+sip) + * @return + * 0 on success, negative value otherwise + */ +__rte_experimental +int +rte_ipsec_sad_del(struct rte_ipsec_sad *sad, + const union rte_ipsec_sad_key *key, + int key_type); +/* + * Create SAD + * + * @param name + * SAD name + * @param conf + * Structure containing the configuration + * @return + * Handle to SAD object on success + * NULL otherwise with rte_errno set to an appropriate values. + */ +__rte_experimental +struct rte_ipsec_sad * +rte_ipsec_sad_create(const char *name, const struct rte_ipsec_sad_conf *conf); + +/** + * Find an existing SAD object and return a pointer to it. + * + * @param name + * Name of the SAD object as passed to rte_ipsec_sad_create() + * @return + * Pointer to sad object or NULL if object not found with rte_errno + * set appropriately. Possible rte_errno values include: + * - ENOENT - required entry not available to return. + */ +__rte_experimental +struct rte_ipsec_sad * +rte_ipsec_sad_find_existing(const char *name); + +/** + * Destroy SAD object. + * + * @param sad + * pointer to the SAD object + * @return + * None + */ +__rte_experimental +void +rte_ipsec_sad_destroy(struct rte_ipsec_sad *sad); + +/** + * Lookup multiple keys in the SAD. + * + * @param sad + * SAD object handle + * @param keys + * Array of keys to be looked up in the SAD + * @param sa + * Pointer assocoated with the keys. + * If the lookup for the given key failed, then corresponding sa + * will be NULL + * @param n + * Number of elements in keys array to lookup. + * @return + * -EINVAL for incorrect arguments, otherwise number of successful lookups. + */ +__rte_experimental +int +rte_ipsec_sad_lookup(const struct rte_ipsec_sad *sad, + const union rte_ipsec_sad_key *keys[], + void *sa[], uint32_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_IPSEC_SAD_H_ */ diff --git a/lib/librte_ipsec/rte_ipsec_version.map b/lib/librte_ipsec/rte_ipsec_version.map index ee9f1961b0..f37c867bf6 100644 --- a/lib/librte_ipsec/rte_ipsec_version.map +++ b/lib/librte_ipsec/rte_ipsec_version.map @@ -8,6 +8,12 @@ EXPERIMENTAL { rte_ipsec_sa_init; rte_ipsec_sa_size; rte_ipsec_sa_type; + rte_ipsec_sad_add; + rte_ipsec_sad_create; + rte_ipsec_sad_del; + rte_ipsec_sad_destroy; + rte_ipsec_sad_find_existing; + rte_ipsec_sad_lookup; rte_ipsec_ses_from_crypto; rte_ipsec_session_prepare;