[RFC,4/4] cryptodev: introduce rte_crypto_cpu_sym_session API

Message ID 20191105184122.15172-5-konstantin.ananyev@intel.com (mailing list archive)
State Changes Requested, archived
Delegated to: akhil goyal
Headers
Series cpu-crypto API choices |

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation success Compilation OK

Commit Message

Ananyev, Konstantin Nov. 5, 2019, 6:41 p.m. UTC
  This patch extends rte_cryptodev API with CPU-CRYPTO mode.
This is done by reusing of existing rte_crypto_sym_xform data structures
and introducing new opaque rte_crypto_cpu_sym_session data structure
and related control and data path API.

Crypto PMD that wants to support that functionality would need to:
1. claim RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO capability supported.
2. implement new functions for rte_cryptodev_ops:
	. cpu_sym_session_size,
	. cpu_sym_session_init,
3. implement new functions for rte_crypto_cpu_sym_session:
	.clear,
	.process
	
For data-path processing consumer would have to maintain:
	struct rte_crypto_cpu_sym_session *sess

Below is a summary of reasons why I think adding new API is a preferable
over reusing existing  rte_crypto_sym_session API:

1. Inside rte_crypto_sym_session there is an array of pointers
to PMD private session structures (indexed by driver id).
Some of them might be initialized, others not.
So even now, user has to maintain a list of dev_ids that
can be used with this session.
With patch #3 in-place it becomes even more complex -
user will have to maintain two lists of dev_ids:
  - one for async crypto-devices that can be used with that session
  - another one for sync crypto-devices that can be used with that session
In majority of examples within dpdk.org tree, we usually don't bother
and use just one device per session.
But for intermediate libraries (librte_ipsec, etc.) that
have to be as generic as possible and can't make such assumptions
such design choice is not very convenient.

From other hand, cpu-crypto is SW based synchronous operation
and it doesn't need any device/queue data during crypto-processing,
all necessary information is stored inside session itself.
The only stage where we really need dev_id - during session init().
So it seems natural to exclude dev_id from data and majority of control
path completely.

2. Current  rte_cryptodev_sym_session_init() expects PMD session data
to be allocated via provided mempool. That seems not very flexible.
Preferred way would be to allow user can allocate memory for cpu-crypto
session whenever he likes.
    
3. Would allow PMD writer to expose a separate process() functions for
different session types and hopefully save extra function call and
reduce data-dependencies for fast-path comparing to previous patch.  

Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
---
 lib/librte_cryptodev/rte_crypto_sym.h    |  8 +++
 lib/librte_cryptodev/rte_cryptodev.c     | 46 +++++++++++++++
 lib/librte_cryptodev/rte_cryptodev.h     | 71 ++++++++++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev_pmd.h | 49 ++++++++++++++++
 4 files changed, 174 insertions(+)
  

Patch

diff --git a/lib/librte_cryptodev/rte_crypto_sym.h b/lib/librte_cryptodev/rte_crypto_sym.h
index d8d9e9514..45f3840bb 100644
--- a/lib/librte_cryptodev/rte_crypto_sym.h
+++ b/lib/librte_cryptodev/rte_crypto_sym.h
@@ -166,6 +166,10 @@  struct rte_crypto_cipher_xform {
 	 *  - Both keys must have the same size.
 	 **/
 
+	/**
+	 * CPU-CRYPTO specific data, used only by rte_crypto_cpu_sym_session
+	 * initialisation pass, otherwise ignored.
+	 */
 	struct {
 		/**
 		 * offset for cipher to start within user provided data buffer.
@@ -415,6 +419,10 @@  struct rte_crypto_aead_xform {
 		uint16_t length;	/**< key length in bytes */
 	} __attribute__((__packed__)) key;
 
+	/**
+	 * CPU-CRYPTO specific data, used only by rte_crypto_cpu_sym_session
+	 * initialisation pass, otherwise ignored.
+	 */
 	struct {
 		/**
 		 * offset for cipher to start within user provided data buffer.
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 89aa2ed3e..8109665c2 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -1616,6 +1616,52 @@  rte_cryptodev_sym_session_get_user_data(
 	return (void *)(sess->sess_data + sess->nb_drivers);
 }
 
+__rte_experimental
+int
+rte_crypto_cpu_sym_session_size(uint8_t dev_id,
+	const struct rte_crypto_sym_xform *xforms)
+{
+	struct rte_cryptodev *dev;
+
+	dev = rte_cryptodev_pmd_get_dev(dev_id);
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->cpu_sym_session_size, -ENOTSUP);
+
+	return dev->dev_ops->cpu_sym_session_size(dev, xforms);
+}
+
+__rte_experimental
+int
+rte_crypto_cpu_sym_session_init(uint8_t dev_id,
+	struct rte_crypto_cpu_sym_session *sess,
+	const struct rte_crypto_sym_xform *xforms)
+{
+	struct rte_cryptodev *dev;
+
+	dev = rte_cryptodev_pmd_get_dev(dev_id);
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->cpu_sym_session_init, -ENOTSUP);
+
+	return dev->dev_ops->cpu_sym_session_init(dev, sess, xforms);
+}
+
+__rte_experimental
+void
+rte_crypto_cpu_sym_session_clear(struct rte_crypto_cpu_sym_session *sess)
+{
+	if (sess != NULL && sess->ops.clear != NULL)
+		return sess->ops.clear(sess);
+}
+
+__rte_experimental
+int
+rte_crypto_cpu_sym_session_process(struct rte_crypto_cpu_sym_session *sess,
+	struct rte_crypto_sym_vec *vec, int32_t status[], uint32_t num)
+{
+	if (sess == NULL || sess->ops.process == NULL)
+		return -EINVAL;
+
+	return sess->ops.process(sess, vec, status, num);
+}
+
 /** Initialise rte_crypto_op mempool element */
 static void
 rte_crypto_op_init(struct rte_mempool *mempool,
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index c6ffa3b35..3333bbe09 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -450,6 +450,8 @@  rte_cryptodev_asym_get_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,
 /**< Support encrypted-digest operations where digest is appended to data */
 #define RTE_CRYPTODEV_FF_ASYM_SESSIONLESS		(1ULL << 20)
 /**< Support asymmetric session-less operations */
+#define RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO		(1ULL << 21)
+/**< Support symmeteric cpu-crypto processing */
 
 
 /**
@@ -1274,6 +1276,75 @@  void *
 rte_cryptodev_sym_session_get_user_data(
 					struct rte_cryptodev_sym_session *sess);
 
+/**
+ * opaque session structure for symmetric CPU-CRYPTO operations.
+ */
+struct rte_crypto_cpu_sym_session;
+
+/**
+ * Calculate required session size in bytes for given set of xforms.
+ * if xforms == NULL, then return the max possible session size,
+ * that would fit session for any supported by the device algorithm.
+ * if CPU-CRYPTO is not supported at all, or requeted in xform
+ * algorithm is not supported, then return -ENOTSUP.
+ * @param   dev_id   ID of device that we want the session to be used on
+ * @param   xforms   Symmetric crypto transform operations to apply on flow
+ *                   processed with this session
+ * @return
+ *  - On success, positive value for required session size in bytes.
+ *  - negative errno value otherwise.
+ */
+__rte_experimental
+int
+rte_crypto_cpu_sym_session_size(uint8_t dev_id,
+		const struct rte_crypto_sym_xform *xforms);
+
+/**
+ * Initialize symmetric CPU-CRYPTO session.
+ * It is caller responsibility to allocate enough space for it.
+ * See rte_crypto_cpu_sym_session_size above.
+ * @param   dev_id   ID of device that we want the session to be used on
+ * @param   sess     Pointer to the raw session buffer
+ * @param   xforms   Symmetric crypto transform operations to apply on flow
+ *                   processed with this session
+ * @return
+ *  - On success, zero.
+ *  - negative errno value otherwise.
+ */
+__rte_experimental
+int
+rte_crypto_cpu_sym_session_init(uint8_t dev_id,
+		struct rte_crypto_cpu_sym_session *sess,
+		const struct rte_crypto_sym_xform *xforms);
+
+/**
+ * De-initialize symmetric CPU-CRYPTO session.
+ * It is caller responsibility to free  the session pointer afterwards.
+ */
+__rte_experimental
+void
+rte_crypto_cpu_sym_session_clear(struct rte_crypto_cpu_sym_session *sess);
+
+/**
+ * Perform actual crypto processing (encrypt/digest or auth/decrypt)
+ * on user provided data.
+ *
+ * @param	sess	cpu-crypto session structure
+ * @param	vec	Array of vectors for input data
+ * @param	status	Array of status values (one per vec)
+ * 			(RTE_CRYPTO_OP_STATUS_* values)
+ * @param	num	Number of elems in vec and status arrays.
+ *
+ * @return
+ *  - Returns negative errno value on error, or non-negative number
+ *    of successfully processed input vectors.
+ *
++*/
+__rte_experimental
+int
+rte_crypto_cpu_sym_session_process(struct rte_crypto_cpu_sym_session *sess,
+	struct rte_crypto_sym_vec *vec, int32_t status[], uint32_t num);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h b/lib/librte_cryptodev/rte_cryptodev_pmd.h
index fba14f2fa..629461315 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.h
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h
@@ -309,6 +309,38 @@  typedef void (*cryptodev_sym_free_session_t)(struct rte_cryptodev *dev,
 typedef void (*cryptodev_asym_free_session_t)(struct rte_cryptodev *dev,
 		struct rte_cryptodev_asym_session *sess);
 
+/**
+ * Calculate required session size in bytes for given set of xforms.
+ * if xforms == NULL, then return the max possible session size,
+ * that would fit session for any supported by the device algorithm.
+ * if CPU-CRYPTO is not supported at all, or requeted in xform
+ * algorithm is not supported, then return -ENOTSUP.
+ * @param	dev	Crypto device pointer
+ * @param	xforms	Symmetric crypto transform operations to apply on flow
+ *                      processed with this session
+ * @return
+ *  - On success, positive value for required session size in bytes.
+ *  - negative errno value otherwise.
+ */
+typedef int (*cryptodev_cpu_sym_session_size_t)(struct rte_cryptodev *dev,
+		const struct rte_crypto_sym_xform *xforms);
+
+/**
+ * Initialize symmetric CPU-CRYPTO session.
+ * It is caller responsibility to allocate enough space for it.
+ * See rte_crypto_cpu_sym_session_size above.
+ * @param	dev	Crypto device pointer
+ * @param	sess	Pointer to the raw session buffer
+ * @param	xforms	Symmetric crypto transform operations to apply on flow
+ *                       processed with this session
+ * @return
+ *  - On success, zero.
+ *  - negative errno value otherwise.
+ */
+typedef int (*cryptodev_cpu_sym_session_init_t)(struct rte_cryptodev *dev,
+		struct rte_crypto_cpu_sym_session *sess,
+		const struct rte_crypto_sym_xform *xforms);
+
 /** Crypto device operations function pointer table */
 struct rte_cryptodev_ops {
 	cryptodev_configure_t dev_configure;	/**< Configure device. */
@@ -342,6 +374,10 @@  struct rte_cryptodev_ops {
 	/**< Clear a Crypto sessions private data. */
 	cryptodev_asym_free_session_t asym_session_clear;
 	/**< Clear a Crypto sessions private data. */
+	cryptodev_cpu_sym_session_size_t cpu_sym_session_size;
+	/**< Calculate required cpu-crypto session size. */
+	cryptodev_cpu_sym_session_init_t cpu_sym_session_init;
+	/**< Initialise cpu-crypto session. */
 };
 
 
@@ -506,6 +542,19 @@  set_asym_session_private_data(struct rte_cryptodev_asym_session *sess,
 	sess->sess_private_data[driver_id] = private_data;
 }
 
+
+struct rte_crypto_cpu_sym_session_ops {
+	void (*clear)(struct rte_crypto_cpu_sym_session *);
+	int (*process)(struct rte_crypto_cpu_sym_session *,
+		struct rte_crypto_sym_vec *, int32_t [], uint32_t);
+};
+
+struct rte_crypto_cpu_sym_session {
+	struct rte_crypto_cpu_sym_session_ops ops;
+	/** session private data starts here. */
+	void *sess_data[0] __rte_cache_min_aligned;
+};
+
 #ifdef __cplusplus
 }
 #endif