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(+)
@@ -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.
@@ -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,
@@ -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
@@ -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