From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id 0BA4D1B58A for ; Tue, 9 Oct 2018 20:24:16 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Oct 2018 11:24:15 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,361,1534834800"; d="scan'208";a="77469435" Received: from sivswdev02.ir.intel.com (HELO localhost.localdomain) ([10.237.217.46]) by fmsmga008.fm.intel.com with ESMTP; 09 Oct 2018 11:23:55 -0700 From: Konstantin Ananyev To: dev@dpdk.org Cc: Konstantin Ananyev , Mohammad Abdul Awal Date: Tue, 9 Oct 2018 19:23:36 +0100 Message-Id: <1539109420-13412-6-git-send-email-konstantin.ananyev@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1535129598-27301-1-git-send-email-konstantin.ananyev@intel.com> References: <1535129598-27301-1-git-send-email-konstantin.ananyev@intel.com> Subject: [dpdk-dev] [RFC v2 5/9] ipsec: add SA data-path API X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 09 Oct 2018 18:24:17 -0000 Introduce Security Association (SA-level) data-path API Operates at SA level, provides functions to: - initialize/teardown SA object - process inbound/outbound ESP/AH packets associated with the given SA (decrypt/encrypt, authenticate, check integrity, add/remove ESP/AH related headers and data, etc.). Signed-off-by: Mohammad Abdul Awal Signed-off-by: Konstantin Ananyev --- lib/librte_ipsec/Makefile | 2 + lib/librte_ipsec/meson.build | 4 +- lib/librte_ipsec/rte_ipsec.h | 154 +++++++++++++++++++++++++++++++++ lib/librte_ipsec/rte_ipsec_version.map | 3 + lib/librte_ipsec/sa.c | 98 ++++++++++++++++++++- lib/librte_ipsec/sa.h | 3 + lib/librte_ipsec/ses.c | 45 ++++++++++ 7 files changed, 306 insertions(+), 3 deletions(-) create mode 100644 lib/librte_ipsec/rte_ipsec.h create mode 100644 lib/librte_ipsec/ses.c diff --git a/lib/librte_ipsec/Makefile b/lib/librte_ipsec/Makefile index 7758dcc6d..79f187fae 100644 --- a/lib/librte_ipsec/Makefile +++ b/lib/librte_ipsec/Makefile @@ -17,8 +17,10 @@ LIBABIVER := 1 # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += sa.c +SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += ses.c # install header files +SYMLINK-$(CONFIG_RTE_LIBRTE_IPSEC)-include += rte_ipsec.h SYMLINK-$(CONFIG_RTE_LIBRTE_IPSEC)-include += rte_ipsec_sa.h include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_ipsec/meson.build b/lib/librte_ipsec/meson.build index 52c78eaeb..6e8c6fabe 100644 --- a/lib/librte_ipsec/meson.build +++ b/lib/librte_ipsec/meson.build @@ -3,8 +3,8 @@ allow_experimental_apis = true -sources=files('sa.c') +sources=files('sa.c', 'ses.c') -install_headers = files('rte_ipsec_sa.h') +install_headers = files('rte_ipsec.h', 'rte_ipsec_sa.h') deps += ['mbuf', 'net', 'cryptodev', 'security'] diff --git a/lib/librte_ipsec/rte_ipsec.h b/lib/librte_ipsec/rte_ipsec.h new file mode 100644 index 000000000..5c9a1ed0b --- /dev/null +++ b/lib/librte_ipsec/rte_ipsec.h @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef _RTE_IPSEC_H_ +#define _RTE_IPSEC_H_ + +/** + * @file rte_ipsec.h + * @b EXPERIMENTAL: this API may change without prior notice + * + * RTE IPsec support. + * librte_ipsec provides a framework for data-path IPsec protocol + * processing (ESP/AH). + * IKEv2 protocol support right now is out of scope of that draft. + * Though it tries to define related API in such way, that it could be adopted + * by IKEv2 implementation. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct rte_ipsec_session; + +/** + * IPsec session specific functions that will be used to: + * - prepare - for input mbufs and given IPsec session prepare crypto ops + * that can be enqueued into the cryptodev associated with given session + * (see *rte_ipsec_crypto_prepare* below for more details). + * - process - finalize processing of packets after crypto-dev finished + * with them or process packets that are subjects to inline IPsec offload + * (see rte_ipsec_process for more details). + */ +struct rte_ipsec_sa_func { + uint16_t (*prepare)(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], + struct rte_crypto_op *cop[], + uint16_t num); + uint16_t (*process)(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], + uint16_t num); +}; + +/** + * rte_ipsec_session is an aggregate structure that defines particular + * IPsec Security Association IPsec (SA) on given security/crypto device: + * - pointer to the SA object + * - security session action type + * - pointer to security/crypto session, plus other related data + * - session/device specific functions to prepare/process IPsec packets. + */ +struct rte_ipsec_session { + + /** + * SA that session belongs to. + * Note that multiple sessions can belong to the same SA. + */ + struct rte_ipsec_sa *sa; + /** session action type */ + enum rte_security_session_action_type type; + /** session and related data */ + union { + struct { + struct rte_cryptodev_sym_session *ses; + } crypto; + struct { + struct rte_security_session *ses; + struct rte_security_ctx *ctx; + uint32_t ol_flags; + } security; + }; + /** functions to prepare/process IPsec packets */ + struct rte_ipsec_sa_func func; +}; + +/** + * Checks that inside given rte_ipsec_session crypto/security fields + * are filled correctly and setups function pointers based on these values. + * @param ss + * Pointer to the *rte_ipsec_session* object + * @return + * - Zero if operation completed successfully. + * - -EINVAL if the parameters are invalid. + */ +int __rte_experimental +rte_ipsec_session_prepare(struct rte_ipsec_session *ss); + +/** + * For input mbufs and given IPsec session prepare crypto ops that can be + * enqueued into the cryptodev associated with given session. + * expects that for each input packet: + * - l2_len, l3_len are setup correctly + * Note that erroneous mbufs are not freed by the function, + * but are placed beyond last valid mbuf in the *mb* array. + * It is a user responsibility to handle them further. + * @param ss + * Pointer to the *rte_ipsec_session* object the packets belong to. + * @param mb + * The address of an array of *num* pointers to *rte_mbuf* structures + * which contain the input packets. + * @param cop + * The address of an array of *num* pointers to the output *rte_crypto_op* + * structures. + * @param num + * The maximum number of packets to process. + * @return + * Number of successfully processed packets, with error code set in rte_errno. + */ +static inline uint16_t __rte_experimental +rte_ipsec_crypto_prepare(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num) +{ + return ss->func.prepare(ss, mb, cop, num); +} + +/** + * Finalise processing of packets after crypto-dev finished with them or + * process packets that are subjects to inline IPsec offload. + * Expects that for each input packet: + * - l2_len, l3_len are setup correctly + * Output mbufs will be: + * inbound - decrypted & authenticated, ESP(AH) related headers removed, + * *l2_len* and *l3_len* fields are updated. + * outbound - appropriate mbuf fields (ol_flags, tx_offloads, etc.) + * properly setup, if necessary - IP headers updated, ESP(AH) fields added, + * Note that erroneous mbufs are not freed by the function, + * but are placed beyond last valid mbuf in the *mb* array. + * It is a user responsibility to handle them further. + * @param ss + * Pointer to the *rte_ipsec_session* object the packets belong to. + * @param mb + * The address of an array of *num* pointers to *rte_mbuf* structures + * which contain the input packets. + * @param num + * The maximum number of packets to process. + * @return + * Number of successfully processed packets, with error code set in rte_errno. + */ +static inline uint16_t __rte_experimental +rte_ipsec_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + uint16_t num) +{ + return ss->func.process(ss, mb, num); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_IPSEC_H_ */ diff --git a/lib/librte_ipsec/rte_ipsec_version.map b/lib/librte_ipsec/rte_ipsec_version.map index 1a66726b8..47620cef5 100644 --- a/lib/librte_ipsec/rte_ipsec_version.map +++ b/lib/librte_ipsec/rte_ipsec_version.map @@ -1,6 +1,9 @@ EXPERIMENTAL { global: + rte_ipsec_crypto_prepare; + rte_ipsec_session_prepare; + rte_ipsec_process; rte_ipsec_sa_fini; rte_ipsec_sa_init; rte_ipsec_sa_size; diff --git a/lib/librte_ipsec/sa.c b/lib/librte_ipsec/sa.c index 913856a3d..ad2aa29df 100644 --- a/lib/librte_ipsec/sa.c +++ b/lib/librte_ipsec/sa.c @@ -2,7 +2,7 @@ * Copyright(c) 2018 Intel Corporation */ -#include +#include #include #include #include @@ -280,3 +280,99 @@ rte_ipsec_sa_init(struct rte_ipsec_sa *sa, const struct rte_ipsec_sa_prm *prm, return sz; } + +static uint16_t +lksd_none_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + struct rte_crypto_op *cop[], uint16_t num) +{ + RTE_SET_USED(ss); + RTE_SET_USED(mb); + RTE_SET_USED(cop); + RTE_SET_USED(num); + rte_errno = ENOTSUP; + return 0; +} + +static uint16_t +lksd_proto_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + struct rte_crypto_op *cop[], uint16_t num) +{ + RTE_SET_USED(ss); + RTE_SET_USED(mb); + RTE_SET_USED(cop); + RTE_SET_USED(num); + rte_errno = ENOTSUP; + return 0; +} + +static uint16_t +lksd_none_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + uint16_t num) +{ + RTE_SET_USED(ss); + RTE_SET_USED(mb); + RTE_SET_USED(num); + rte_errno = ENOTSUP; + return 0; +} + +static uint16_t +inline_crypto_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + uint16_t num) +{ + RTE_SET_USED(ss); + RTE_SET_USED(mb); + RTE_SET_USED(num); + rte_errno = ENOTSUP; + return 0; +} + +static uint16_t +inline_proto_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + uint16_t num) +{ + RTE_SET_USED(ss); + RTE_SET_USED(mb); + RTE_SET_USED(num); + rte_errno = ENOTSUP; + return 0; +} + +static uint16_t +lksd_proto_process(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + uint16_t num) +{ + RTE_SET_USED(ss); + RTE_SET_USED(mb); + RTE_SET_USED(num); + rte_errno = ENOTSUP; + return 0; +} + +const struct rte_ipsec_sa_func * +ipsec_sa_func_select(const struct rte_ipsec_session *ss) +{ + static const struct rte_ipsec_sa_func tfunc[] = { + [RTE_SECURITY_ACTION_TYPE_NONE] = { + .prepare = lksd_none_prepare, + .process = lksd_none_process, + }, + [RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO] = { + .prepare = NULL, + .process = inline_crypto_process, + }, + [RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL] = { + .prepare = NULL, + .process = inline_proto_process, + }, + [RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL] = { + .prepare = lksd_proto_prepare, + .process = lksd_proto_process, + }, + }; + + if (ss->type >= RTE_DIM(tfunc)) + return NULL; + + return tfunc + ss->type; +} diff --git a/lib/librte_ipsec/sa.h b/lib/librte_ipsec/sa.h index ef030334c..13a5a68f3 100644 --- a/lib/librte_ipsec/sa.h +++ b/lib/librte_ipsec/sa.h @@ -72,4 +72,7 @@ struct rte_ipsec_sa { } __rte_cache_aligned; +const struct rte_ipsec_sa_func * +ipsec_sa_func_select(const struct rte_ipsec_session *ss); + #endif /* _SA_H_ */ diff --git a/lib/librte_ipsec/ses.c b/lib/librte_ipsec/ses.c new file mode 100644 index 000000000..afefda937 --- /dev/null +++ b/lib/librte_ipsec/ses.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include +#include "sa.h" + +static int +session_check(struct rte_ipsec_session *ss) +{ + if (ss == NULL) + return -EINVAL; + + if (ss->type == RTE_SECURITY_ACTION_TYPE_NONE) { + if (ss->crypto.ses == NULL) + return -EINVAL; + } else if (ss->security.ses == NULL || ss->security.ctx == NULL) + return -EINVAL; + + return 0; +} + +int __rte_experimental +rte_ipsec_session_prepare(struct rte_ipsec_session *ss) +{ + int32_t rc; + const struct rte_ipsec_sa_func *fp; + + rc = session_check(ss); + if (rc != 0) + return rc; + + fp = ipsec_sa_func_select(ss); + if (fp == NULL) + return -ENOTSUP; + + ss->func = fp[0]; + + if (ss->type == RTE_SECURITY_ACTION_TYPE_NONE) + ss->crypto.ses->userdata = (uintptr_t)ss; + else + ss->security.ses->userdata = (uintptr_t)ss; + + return 0; +} -- 2.13.6