cryptodev: add enqueue and dequeue callbacks
This patch adds APIs to add/remove callback functions on crypto enqueue/dequeue burst. The callback function will be called for each burst of crypto ops received/sent on a given crypto device queue pair. Signed-off-by: Abhinandan Gujjar <abhinandan.gujjar@intel.com> Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
This commit is contained in:
parent
61baeec468
commit
1c3ffb9559
@ -62,6 +62,7 @@
|
|||||||
/* cryptodev defines */
|
/* cryptodev defines */
|
||||||
#define RTE_CRYPTO_MAX_DEVS 64
|
#define RTE_CRYPTO_MAX_DEVS 64
|
||||||
#define RTE_CRYPTODEV_NAME_LEN 64
|
#define RTE_CRYPTODEV_NAME_LEN 64
|
||||||
|
#define RTE_CRYPTO_CALLBACKS 1
|
||||||
|
|
||||||
/* compressdev defines */
|
/* compressdev defines */
|
||||||
#define RTE_COMPRESS_MAX_DEVS 64
|
#define RTE_COMPRESS_MAX_DEVS 64
|
||||||
|
@ -11,3 +11,8 @@
|
|||||||
; Explicit ignore for driver-only ABI
|
; Explicit ignore for driver-only ABI
|
||||||
[suppress_type]
|
[suppress_type]
|
||||||
name = eth_dev_ops
|
name = eth_dev_ops
|
||||||
|
|
||||||
|
; Ignore fields inserted in cacheline boundary of rte_cryptodev
|
||||||
|
[suppress_type]
|
||||||
|
name = rte_cryptodev
|
||||||
|
has_data_member_inserted_between = {0, 1023}
|
||||||
|
@ -338,6 +338,50 @@ start of private data information. The offset is counted from the start of the
|
|||||||
rte_crypto_op including other crypto information such as the IVs (since there can
|
rte_crypto_op including other crypto information such as the IVs (since there can
|
||||||
be an IV also for authentication).
|
be an IV also for authentication).
|
||||||
|
|
||||||
|
User callback APIs
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
The add APIs configures a user callback function to be called for each burst of crypto
|
||||||
|
ops received/sent on a given crypto device queue pair. The return value is a pointer
|
||||||
|
that can be used later to remove the callback using remove API. Application is expected
|
||||||
|
to register a callback function of type ``rte_cryptodev_callback_fn``. Multiple callback
|
||||||
|
functions can be added for a given queue pair. API does not restrict on maximum number of
|
||||||
|
callbacks.
|
||||||
|
|
||||||
|
Callbacks registered by application would not survive ``rte_cryptodev_configure`` as it
|
||||||
|
reinitializes the callback list. It is user responsibility to remove all installed
|
||||||
|
callbacks before calling ``rte_cryptodev_configure`` to avoid possible memory leakage.
|
||||||
|
|
||||||
|
So, the application is expected to add user callback after ``rte_cryptodev_configure``.
|
||||||
|
The callbacks can also be added at the runtime. These callbacks get executed when
|
||||||
|
``rte_cryptodev_enqueue_burst``/``rte_cryptodev_dequeue_burst`` is called.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
struct rte_cryptodev_cb *
|
||||||
|
rte_cryptodev_add_enq_callback(uint8_t dev_id, uint16_t qp_id,
|
||||||
|
rte_cryptodev_callback_fn cb_fn,
|
||||||
|
void *cb_arg);
|
||||||
|
|
||||||
|
struct rte_cryptodev_cb *
|
||||||
|
rte_cryptodev_add_deq_callback(uint8_t dev_id, uint16_t qp_id,
|
||||||
|
rte_cryptodev_callback_fn cb_fn,
|
||||||
|
void *cb_arg);
|
||||||
|
|
||||||
|
uint16_t (* rte_cryptodev_callback_fn)(uint16_t dev_id, uint16_t qp_id,
|
||||||
|
struct rte_crypto_op **ops,
|
||||||
|
uint16_t nb_ops, void *user_param);
|
||||||
|
|
||||||
|
The remove API removes a callback function added by
|
||||||
|
``rte_cryptodev_add_enq_callback``/``rte_cryptodev_add_deq_callback``.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
int rte_cryptodev_remove_enq_callback(uint8_t dev_id, uint16_t qp_id,
|
||||||
|
struct rte_cryptodev_cb *cb);
|
||||||
|
|
||||||
|
int rte_cryptodev_remove_deq_callback(uint8_t dev_id, uint16_t qp_id,
|
||||||
|
struct rte_cryptodev_cb *cb);
|
||||||
|
|
||||||
|
|
||||||
Enqueue / Dequeue Burst APIs
|
Enqueue / Dequeue Burst APIs
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -76,6 +76,12 @@ New Features
|
|||||||
|
|
||||||
* Added inner UDP/IPv4 support for VXLAN IPv4 GSO.
|
* Added inner UDP/IPv4 support for VXLAN IPv4 GSO.
|
||||||
|
|
||||||
|
* **Added enqueue & dequeue callback APIs for cryptodev library.**
|
||||||
|
|
||||||
|
Cryptodev library is added with enqueue & dequeue callback APIs to
|
||||||
|
enable applications to add/remove user callbacks which gets called
|
||||||
|
for every enqueue/dequeue operation.
|
||||||
|
|
||||||
* **Updated the OCTEON TX2 crypto PMD.**
|
* **Updated the OCTEON TX2 crypto PMD.**
|
||||||
|
|
||||||
* Updated the OCTEON TX2 crypto PMD lookaside protocol offload for IPsec with
|
* Updated the OCTEON TX2 crypto PMD lookaside protocol offload for IPsec with
|
||||||
@ -119,6 +125,9 @@ API Changes
|
|||||||
Also, make sure to start the actual text at the margin.
|
Also, make sure to start the actual text at the margin.
|
||||||
=======================================================
|
=======================================================
|
||||||
|
|
||||||
|
* cryptodev: The structure ``rte_cryptodev`` has been updated with pointers
|
||||||
|
for adding enqueue and dequeue callbacks.
|
||||||
|
|
||||||
|
|
||||||
ABI Changes
|
ABI Changes
|
||||||
-----------
|
-----------
|
||||||
|
@ -9,4 +9,4 @@ headers = files('rte_cryptodev.h',
|
|||||||
'rte_crypto.h',
|
'rte_crypto.h',
|
||||||
'rte_crypto_sym.h',
|
'rte_crypto_sym.h',
|
||||||
'rte_crypto_asym.h')
|
'rte_crypto_asym.h')
|
||||||
deps += ['kvargs', 'mbuf']
|
deps += ['kvargs', 'mbuf', 'rcu']
|
||||||
|
@ -448,6 +448,122 @@ rte_cryptodev_asym_xform_capability_check_modlen(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* spinlock for crypto device enq callbacks */
|
||||||
|
static rte_spinlock_t rte_cryptodev_callback_lock = RTE_SPINLOCK_INITIALIZER;
|
||||||
|
|
||||||
|
static void
|
||||||
|
cryptodev_cb_cleanup(struct rte_cryptodev *dev)
|
||||||
|
{
|
||||||
|
struct rte_cryptodev_cb_rcu *list;
|
||||||
|
struct rte_cryptodev_cb *cb, *next;
|
||||||
|
uint16_t qp_id;
|
||||||
|
|
||||||
|
if (dev->enq_cbs == NULL && dev->deq_cbs == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
|
||||||
|
list = &dev->enq_cbs[qp_id];
|
||||||
|
cb = list->next;
|
||||||
|
while (cb != NULL) {
|
||||||
|
next = cb->next;
|
||||||
|
rte_free(cb);
|
||||||
|
cb = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_free(list->qsbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
|
||||||
|
list = &dev->deq_cbs[qp_id];
|
||||||
|
cb = list->next;
|
||||||
|
while (cb != NULL) {
|
||||||
|
next = cb->next;
|
||||||
|
rte_free(cb);
|
||||||
|
cb = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_free(list->qsbr);
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_free(dev->enq_cbs);
|
||||||
|
dev->enq_cbs = NULL;
|
||||||
|
rte_free(dev->deq_cbs);
|
||||||
|
dev->deq_cbs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cryptodev_cb_init(struct rte_cryptodev *dev)
|
||||||
|
{
|
||||||
|
struct rte_cryptodev_cb_rcu *list;
|
||||||
|
struct rte_rcu_qsbr *qsbr;
|
||||||
|
uint16_t qp_id;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
/* Max thread set to 1, as one DP thread accessing a queue-pair */
|
||||||
|
const uint32_t max_threads = 1;
|
||||||
|
|
||||||
|
dev->enq_cbs = rte_zmalloc(NULL,
|
||||||
|
sizeof(struct rte_cryptodev_cb_rcu) *
|
||||||
|
dev->data->nb_queue_pairs, 0);
|
||||||
|
if (dev->enq_cbs == NULL) {
|
||||||
|
CDEV_LOG_ERR("Failed to allocate memory for enq callbacks");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->deq_cbs = rte_zmalloc(NULL,
|
||||||
|
sizeof(struct rte_cryptodev_cb_rcu) *
|
||||||
|
dev->data->nb_queue_pairs, 0);
|
||||||
|
if (dev->deq_cbs == NULL) {
|
||||||
|
CDEV_LOG_ERR("Failed to allocate memory for deq callbacks");
|
||||||
|
rte_free(dev->enq_cbs);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create RCU QSBR variable */
|
||||||
|
size = rte_rcu_qsbr_get_memsize(max_threads);
|
||||||
|
|
||||||
|
for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
|
||||||
|
list = &dev->enq_cbs[qp_id];
|
||||||
|
qsbr = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
|
||||||
|
if (qsbr == NULL) {
|
||||||
|
CDEV_LOG_ERR("Failed to allocate memory for RCU on "
|
||||||
|
"queue_pair_id=%d", qp_id);
|
||||||
|
goto cb_init_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rte_rcu_qsbr_init(qsbr, max_threads)) {
|
||||||
|
CDEV_LOG_ERR("Failed to initialize for RCU on "
|
||||||
|
"queue_pair_id=%d", qp_id);
|
||||||
|
goto cb_init_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->qsbr = qsbr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
|
||||||
|
list = &dev->deq_cbs[qp_id];
|
||||||
|
qsbr = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
|
||||||
|
if (qsbr == NULL) {
|
||||||
|
CDEV_LOG_ERR("Failed to allocate memory for RCU on "
|
||||||
|
"queue_pair_id=%d", qp_id);
|
||||||
|
goto cb_init_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rte_rcu_qsbr_init(qsbr, max_threads)) {
|
||||||
|
CDEV_LOG_ERR("Failed to initialize for RCU on "
|
||||||
|
"queue_pair_id=%d", qp_id);
|
||||||
|
goto cb_init_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->qsbr = qsbr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cb_init_err:
|
||||||
|
cryptodev_cb_cleanup(dev);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
rte_cryptodev_get_feature_name(uint64_t flag)
|
rte_cryptodev_get_feature_name(uint64_t flag)
|
||||||
@ -927,6 +1043,10 @@ rte_cryptodev_configure(uint8_t dev_id, struct rte_cryptodev_config *config)
|
|||||||
|
|
||||||
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
|
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
|
||||||
|
|
||||||
|
rte_spinlock_lock(&rte_cryptodev_callback_lock);
|
||||||
|
cryptodev_cb_cleanup(dev);
|
||||||
|
rte_spinlock_unlock(&rte_cryptodev_callback_lock);
|
||||||
|
|
||||||
/* Setup new number of queue pairs and reconfigure device. */
|
/* Setup new number of queue pairs and reconfigure device. */
|
||||||
diag = rte_cryptodev_queue_pairs_config(dev, config->nb_queue_pairs,
|
diag = rte_cryptodev_queue_pairs_config(dev, config->nb_queue_pairs,
|
||||||
config->socket_id);
|
config->socket_id);
|
||||||
@ -936,11 +1056,18 @@ rte_cryptodev_configure(uint8_t dev_id, struct rte_cryptodev_config *config)
|
|||||||
return diag;
|
return diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rte_spinlock_lock(&rte_cryptodev_callback_lock);
|
||||||
|
diag = cryptodev_cb_init(dev);
|
||||||
|
rte_spinlock_unlock(&rte_cryptodev_callback_lock);
|
||||||
|
if (diag) {
|
||||||
|
CDEV_LOG_ERR("Callback init failed for dev_id=%d", dev_id);
|
||||||
|
return diag;
|
||||||
|
}
|
||||||
|
|
||||||
rte_cryptodev_trace_configure(dev_id, config);
|
rte_cryptodev_trace_configure(dev_id, config);
|
||||||
return (*dev->dev_ops->dev_configure)(dev, config);
|
return (*dev->dev_ops->dev_configure)(dev, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
rte_cryptodev_start(uint8_t dev_id)
|
rte_cryptodev_start(uint8_t dev_id)
|
||||||
{
|
{
|
||||||
@ -1136,6 +1263,275 @@ rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
|
|||||||
socket_id);
|
socket_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct rte_cryptodev_cb *
|
||||||
|
rte_cryptodev_add_enq_callback(uint8_t dev_id,
|
||||||
|
uint16_t qp_id,
|
||||||
|
rte_cryptodev_callback_fn cb_fn,
|
||||||
|
void *cb_arg)
|
||||||
|
{
|
||||||
|
struct rte_cryptodev *dev;
|
||||||
|
struct rte_cryptodev_cb_rcu *list;
|
||||||
|
struct rte_cryptodev_cb *cb, *tail;
|
||||||
|
|
||||||
|
if (!cb_fn) {
|
||||||
|
CDEV_LOG_ERR("Callback is NULL on dev_id=%d", dev_id);
|
||||||
|
rte_errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
||||||
|
CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
|
||||||
|
rte_errno = ENODEV;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = &rte_crypto_devices[dev_id];
|
||||||
|
if (qp_id >= dev->data->nb_queue_pairs) {
|
||||||
|
CDEV_LOG_ERR("Invalid queue_pair_id=%d", qp_id);
|
||||||
|
rte_errno = ENODEV;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb = rte_zmalloc(NULL, sizeof(*cb), 0);
|
||||||
|
if (cb == NULL) {
|
||||||
|
CDEV_LOG_ERR("Failed to allocate memory for callback on "
|
||||||
|
"dev=%d, queue_pair_id=%d", dev_id, qp_id);
|
||||||
|
rte_errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_spinlock_lock(&rte_cryptodev_callback_lock);
|
||||||
|
|
||||||
|
cb->fn = cb_fn;
|
||||||
|
cb->arg = cb_arg;
|
||||||
|
|
||||||
|
/* Add the callbacks in fifo order. */
|
||||||
|
list = &dev->enq_cbs[qp_id];
|
||||||
|
tail = list->next;
|
||||||
|
|
||||||
|
if (tail) {
|
||||||
|
while (tail->next)
|
||||||
|
tail = tail->next;
|
||||||
|
/* Stores to cb->fn and cb->param should complete before
|
||||||
|
* cb is visible to data plane.
|
||||||
|
*/
|
||||||
|
__atomic_store_n(&tail->next, cb, __ATOMIC_RELEASE);
|
||||||
|
} else {
|
||||||
|
/* Stores to cb->fn and cb->param should complete before
|
||||||
|
* cb is visible to data plane.
|
||||||
|
*/
|
||||||
|
__atomic_store_n(&list->next, cb, __ATOMIC_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_spinlock_unlock(&rte_cryptodev_callback_lock);
|
||||||
|
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rte_cryptodev_remove_enq_callback(uint8_t dev_id,
|
||||||
|
uint16_t qp_id,
|
||||||
|
struct rte_cryptodev_cb *cb)
|
||||||
|
{
|
||||||
|
struct rte_cryptodev *dev;
|
||||||
|
struct rte_cryptodev_cb **prev_cb, *curr_cb;
|
||||||
|
struct rte_cryptodev_cb_rcu *list;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = -EINVAL;
|
||||||
|
|
||||||
|
if (!cb) {
|
||||||
|
CDEV_LOG_ERR("Callback is NULL");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
||||||
|
CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = &rte_crypto_devices[dev_id];
|
||||||
|
if (qp_id >= dev->data->nb_queue_pairs) {
|
||||||
|
CDEV_LOG_ERR("Invalid queue_pair_id=%d", qp_id);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_spinlock_lock(&rte_cryptodev_callback_lock);
|
||||||
|
if (dev->enq_cbs == NULL) {
|
||||||
|
CDEV_LOG_ERR("Callback not initialized");
|
||||||
|
goto cb_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = &dev->enq_cbs[qp_id];
|
||||||
|
if (list == NULL) {
|
||||||
|
CDEV_LOG_ERR("Callback list is NULL");
|
||||||
|
goto cb_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list->qsbr == NULL) {
|
||||||
|
CDEV_LOG_ERR("Rcu qsbr is NULL");
|
||||||
|
goto cb_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_cb = &list->next;
|
||||||
|
for (; *prev_cb != NULL; prev_cb = &curr_cb->next) {
|
||||||
|
curr_cb = *prev_cb;
|
||||||
|
if (curr_cb == cb) {
|
||||||
|
/* Remove the user cb from the callback list. */
|
||||||
|
__atomic_store_n(prev_cb, curr_cb->next,
|
||||||
|
__ATOMIC_RELAXED);
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
/* Call sync with invalid thread id as this is part of
|
||||||
|
* control plane API
|
||||||
|
*/
|
||||||
|
rte_rcu_qsbr_synchronize(list->qsbr, RTE_QSBR_THRID_INVALID);
|
||||||
|
rte_free(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_err:
|
||||||
|
rte_spinlock_unlock(&rte_cryptodev_callback_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rte_cryptodev_cb *
|
||||||
|
rte_cryptodev_add_deq_callback(uint8_t dev_id,
|
||||||
|
uint16_t qp_id,
|
||||||
|
rte_cryptodev_callback_fn cb_fn,
|
||||||
|
void *cb_arg)
|
||||||
|
{
|
||||||
|
struct rte_cryptodev *dev;
|
||||||
|
struct rte_cryptodev_cb_rcu *list;
|
||||||
|
struct rte_cryptodev_cb *cb, *tail;
|
||||||
|
|
||||||
|
if (!cb_fn) {
|
||||||
|
CDEV_LOG_ERR("Callback is NULL on dev_id=%d", dev_id);
|
||||||
|
rte_errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
||||||
|
CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
|
||||||
|
rte_errno = ENODEV;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = &rte_crypto_devices[dev_id];
|
||||||
|
if (qp_id >= dev->data->nb_queue_pairs) {
|
||||||
|
CDEV_LOG_ERR("Invalid queue_pair_id=%d", qp_id);
|
||||||
|
rte_errno = ENODEV;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb = rte_zmalloc(NULL, sizeof(*cb), 0);
|
||||||
|
if (cb == NULL) {
|
||||||
|
CDEV_LOG_ERR("Failed to allocate memory for callback on "
|
||||||
|
"dev=%d, queue_pair_id=%d", dev_id, qp_id);
|
||||||
|
rte_errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_spinlock_lock(&rte_cryptodev_callback_lock);
|
||||||
|
|
||||||
|
cb->fn = cb_fn;
|
||||||
|
cb->arg = cb_arg;
|
||||||
|
|
||||||
|
/* Add the callbacks in fifo order. */
|
||||||
|
list = &dev->deq_cbs[qp_id];
|
||||||
|
tail = list->next;
|
||||||
|
|
||||||
|
if (tail) {
|
||||||
|
while (tail->next)
|
||||||
|
tail = tail->next;
|
||||||
|
/* Stores to cb->fn and cb->param should complete before
|
||||||
|
* cb is visible to data plane.
|
||||||
|
*/
|
||||||
|
__atomic_store_n(&tail->next, cb, __ATOMIC_RELEASE);
|
||||||
|
} else {
|
||||||
|
/* Stores to cb->fn and cb->param should complete before
|
||||||
|
* cb is visible to data plane.
|
||||||
|
*/
|
||||||
|
__atomic_store_n(&list->next, cb, __ATOMIC_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_spinlock_unlock(&rte_cryptodev_callback_lock);
|
||||||
|
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rte_cryptodev_remove_deq_callback(uint8_t dev_id,
|
||||||
|
uint16_t qp_id,
|
||||||
|
struct rte_cryptodev_cb *cb)
|
||||||
|
{
|
||||||
|
struct rte_cryptodev *dev;
|
||||||
|
struct rte_cryptodev_cb **prev_cb, *curr_cb;
|
||||||
|
struct rte_cryptodev_cb_rcu *list;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = -EINVAL;
|
||||||
|
|
||||||
|
if (!cb) {
|
||||||
|
CDEV_LOG_ERR("Callback is NULL");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
|
||||||
|
CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = &rte_crypto_devices[dev_id];
|
||||||
|
if (qp_id >= dev->data->nb_queue_pairs) {
|
||||||
|
CDEV_LOG_ERR("Invalid queue_pair_id=%d", qp_id);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
rte_spinlock_lock(&rte_cryptodev_callback_lock);
|
||||||
|
if (dev->enq_cbs == NULL) {
|
||||||
|
CDEV_LOG_ERR("Callback not initialized");
|
||||||
|
goto cb_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
list = &dev->deq_cbs[qp_id];
|
||||||
|
if (list == NULL) {
|
||||||
|
CDEV_LOG_ERR("Callback list is NULL");
|
||||||
|
goto cb_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list->qsbr == NULL) {
|
||||||
|
CDEV_LOG_ERR("Rcu qsbr is NULL");
|
||||||
|
goto cb_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_cb = &list->next;
|
||||||
|
for (; *prev_cb != NULL; prev_cb = &curr_cb->next) {
|
||||||
|
curr_cb = *prev_cb;
|
||||||
|
if (curr_cb == cb) {
|
||||||
|
/* Remove the user cb from the callback list. */
|
||||||
|
__atomic_store_n(prev_cb, curr_cb->next,
|
||||||
|
__ATOMIC_RELAXED);
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
/* Call sync with invalid thread id as this is part of
|
||||||
|
* control plane API
|
||||||
|
*/
|
||||||
|
rte_rcu_qsbr_synchronize(list->qsbr, RTE_QSBR_THRID_INVALID);
|
||||||
|
rte_free(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
cb_err:
|
||||||
|
rte_spinlock_unlock(&rte_cryptodev_callback_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rte_cryptodev_stats_get(uint8_t dev_id, struct rte_cryptodev_stats *stats)
|
rte_cryptodev_stats_get(uint8_t dev_id, struct rte_cryptodev_stats *stats)
|
||||||
|
@ -23,6 +23,7 @@ extern "C" {
|
|||||||
#include "rte_dev.h"
|
#include "rte_dev.h"
|
||||||
#include <rte_common.h>
|
#include <rte_common.h>
|
||||||
#include <rte_config.h>
|
#include <rte_config.h>
|
||||||
|
#include <rte_rcu_qsbr.h>
|
||||||
|
|
||||||
#include "rte_cryptodev_trace_fp.h"
|
#include "rte_cryptodev_trace_fp.h"
|
||||||
|
|
||||||
@ -522,6 +523,30 @@ struct rte_cryptodev_qp_conf {
|
|||||||
/**< The mempool for creating sess private data in sessionless mode */
|
/**< The mempool for creating sess private data in sessionless mode */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function type used for processing crypto ops when enqueue/dequeue burst is
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* The callback function is called on enqueue/dequeue burst immediately.
|
||||||
|
*
|
||||||
|
* @param dev_id The identifier of the device.
|
||||||
|
* @param qp_id The index of the queue pair on which ops are
|
||||||
|
* enqueued/dequeued. The value must be in the
|
||||||
|
* range [0, nb_queue_pairs - 1] previously
|
||||||
|
* supplied to *rte_cryptodev_configure*.
|
||||||
|
* @param ops The address of an array of *nb_ops* pointers
|
||||||
|
* to *rte_crypto_op* structures which contain
|
||||||
|
* the crypto operations to be processed.
|
||||||
|
* @param nb_ops The number of operations to process.
|
||||||
|
* @param user_param The arbitrary user parameter passed in by the
|
||||||
|
* application when the callback was originally
|
||||||
|
* registered.
|
||||||
|
* @return The number of ops to be enqueued to the
|
||||||
|
* crypto device.
|
||||||
|
*/
|
||||||
|
typedef uint16_t (*rte_cryptodev_callback_fn)(uint16_t dev_id, uint16_t qp_id,
|
||||||
|
struct rte_crypto_op **ops, uint16_t nb_ops, void *user_param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Typedef for application callback function to be registered by application
|
* Typedef for application callback function to be registered by application
|
||||||
* software for notification of device events
|
* software for notification of device events
|
||||||
@ -822,7 +847,6 @@ rte_cryptodev_callback_unregister(uint8_t dev_id,
|
|||||||
enum rte_cryptodev_event_type event,
|
enum rte_cryptodev_event_type event,
|
||||||
rte_cryptodev_cb_fn cb_fn, void *cb_arg);
|
rte_cryptodev_cb_fn cb_fn, void *cb_arg);
|
||||||
|
|
||||||
|
|
||||||
typedef uint16_t (*dequeue_pkt_burst_t)(void *qp,
|
typedef uint16_t (*dequeue_pkt_burst_t)(void *qp,
|
||||||
struct rte_crypto_op **ops, uint16_t nb_ops);
|
struct rte_crypto_op **ops, uint16_t nb_ops);
|
||||||
/**< Dequeue processed packets from queue pair of a device. */
|
/**< Dequeue processed packets from queue pair of a device. */
|
||||||
@ -839,6 +863,30 @@ struct rte_cryptodev_callback;
|
|||||||
/** Structure to keep track of registered callbacks */
|
/** Structure to keep track of registered callbacks */
|
||||||
TAILQ_HEAD(rte_cryptodev_cb_list, rte_cryptodev_callback);
|
TAILQ_HEAD(rte_cryptodev_cb_list, rte_cryptodev_callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure used to hold information about the callbacks to be called for a
|
||||||
|
* queue pair on enqueue/dequeue.
|
||||||
|
*/
|
||||||
|
struct rte_cryptodev_cb {
|
||||||
|
struct rte_cryptodev_cb *next;
|
||||||
|
/**< Pointer to next callback */
|
||||||
|
rte_cryptodev_callback_fn fn;
|
||||||
|
/**< Pointer to callback function */
|
||||||
|
void *arg;
|
||||||
|
/**< Pointer to argument */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* Structure used to hold information about the RCU for a queue pair.
|
||||||
|
*/
|
||||||
|
struct rte_cryptodev_cb_rcu {
|
||||||
|
struct rte_cryptodev_cb *next;
|
||||||
|
/**< Pointer to next callback */
|
||||||
|
struct rte_rcu_qsbr *qsbr;
|
||||||
|
/**< RCU QSBR variable per queue pair */
|
||||||
|
};
|
||||||
|
|
||||||
/** The data structure associated with each crypto device. */
|
/** The data structure associated with each crypto device. */
|
||||||
struct rte_cryptodev {
|
struct rte_cryptodev {
|
||||||
dequeue_pkt_burst_t dequeue_burst;
|
dequeue_pkt_burst_t dequeue_burst;
|
||||||
@ -867,6 +915,12 @@ struct rte_cryptodev {
|
|||||||
__extension__
|
__extension__
|
||||||
uint8_t attached : 1;
|
uint8_t attached : 1;
|
||||||
/**< Flag indicating the device is attached */
|
/**< Flag indicating the device is attached */
|
||||||
|
|
||||||
|
struct rte_cryptodev_cb_rcu *enq_cbs;
|
||||||
|
/**< User application callback for pre enqueue processing */
|
||||||
|
|
||||||
|
struct rte_cryptodev_cb_rcu *deq_cbs;
|
||||||
|
/**< User application callback for post dequeue processing */
|
||||||
} __rte_cache_aligned;
|
} __rte_cache_aligned;
|
||||||
|
|
||||||
void *
|
void *
|
||||||
@ -945,10 +999,33 @@ rte_cryptodev_dequeue_burst(uint8_t dev_id, uint16_t qp_id,
|
|||||||
{
|
{
|
||||||
struct rte_cryptodev *dev = &rte_cryptodevs[dev_id];
|
struct rte_cryptodev *dev = &rte_cryptodevs[dev_id];
|
||||||
|
|
||||||
|
rte_cryptodev_trace_dequeue_burst(dev_id, qp_id, (void **)ops, nb_ops);
|
||||||
nb_ops = (*dev->dequeue_burst)
|
nb_ops = (*dev->dequeue_burst)
|
||||||
(dev->data->queue_pairs[qp_id], ops, nb_ops);
|
(dev->data->queue_pairs[qp_id], ops, nb_ops);
|
||||||
|
#ifdef RTE_CRYPTO_CALLBACKS
|
||||||
|
if (unlikely(dev->deq_cbs != NULL)) {
|
||||||
|
struct rte_cryptodev_cb_rcu *list;
|
||||||
|
struct rte_cryptodev_cb *cb;
|
||||||
|
|
||||||
rte_cryptodev_trace_dequeue_burst(dev_id, qp_id, (void **)ops, nb_ops);
|
/* __ATOMIC_RELEASE memory order was used when the
|
||||||
|
* call back was inserted into the list.
|
||||||
|
* Since there is a clear dependency between loading
|
||||||
|
* cb and cb->fn/cb->next, __ATOMIC_ACQUIRE memory order is
|
||||||
|
* not required.
|
||||||
|
*/
|
||||||
|
list = &dev->deq_cbs[qp_id];
|
||||||
|
rte_rcu_qsbr_thread_online(list->qsbr, 0);
|
||||||
|
cb = __atomic_load_n(&list->next, __ATOMIC_RELAXED);
|
||||||
|
|
||||||
|
while (cb != NULL) {
|
||||||
|
nb_ops = cb->fn(dev_id, qp_id, ops, nb_ops,
|
||||||
|
cb->arg);
|
||||||
|
cb = cb->next;
|
||||||
|
};
|
||||||
|
|
||||||
|
rte_rcu_qsbr_thread_offline(list->qsbr, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return nb_ops;
|
return nb_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -989,6 +1066,31 @@ rte_cryptodev_enqueue_burst(uint8_t dev_id, uint16_t qp_id,
|
|||||||
{
|
{
|
||||||
struct rte_cryptodev *dev = &rte_cryptodevs[dev_id];
|
struct rte_cryptodev *dev = &rte_cryptodevs[dev_id];
|
||||||
|
|
||||||
|
#ifdef RTE_CRYPTO_CALLBACKS
|
||||||
|
if (unlikely(dev->enq_cbs != NULL)) {
|
||||||
|
struct rte_cryptodev_cb_rcu *list;
|
||||||
|
struct rte_cryptodev_cb *cb;
|
||||||
|
|
||||||
|
/* __ATOMIC_RELEASE memory order was used when the
|
||||||
|
* call back was inserted into the list.
|
||||||
|
* Since there is a clear dependency between loading
|
||||||
|
* cb and cb->fn/cb->next, __ATOMIC_ACQUIRE memory order is
|
||||||
|
* not required.
|
||||||
|
*/
|
||||||
|
list = &dev->enq_cbs[qp_id];
|
||||||
|
rte_rcu_qsbr_thread_online(list->qsbr, 0);
|
||||||
|
cb = __atomic_load_n(&list->next, __ATOMIC_RELAXED);
|
||||||
|
|
||||||
|
while (cb != NULL) {
|
||||||
|
nb_ops = cb->fn(dev_id, qp_id, ops, nb_ops,
|
||||||
|
cb->arg);
|
||||||
|
cb = cb->next;
|
||||||
|
};
|
||||||
|
|
||||||
|
rte_rcu_qsbr_thread_offline(list->qsbr, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
rte_cryptodev_trace_enqueue_burst(dev_id, qp_id, (void **)ops, nb_ops);
|
rte_cryptodev_trace_enqueue_burst(dev_id, qp_id, (void **)ops, nb_ops);
|
||||||
return (*dev->enqueue_burst)(
|
return (*dev->enqueue_burst)(
|
||||||
dev->data->queue_pairs[qp_id], ops, nb_ops);
|
dev->data->queue_pairs[qp_id], ops, nb_ops);
|
||||||
@ -1730,6 +1832,144 @@ int
|
|||||||
rte_cryptodev_raw_dequeue_done(struct rte_crypto_raw_dp_ctx *ctx,
|
rte_cryptodev_raw_dequeue_done(struct rte_crypto_raw_dp_ctx *ctx,
|
||||||
uint32_t n);
|
uint32_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a user callback for a given crypto device and queue pair which will be
|
||||||
|
* called on crypto ops enqueue.
|
||||||
|
*
|
||||||
|
* This API configures a function to be called for each burst of crypto ops
|
||||||
|
* received on a given crypto device queue pair. The return value is a pointer
|
||||||
|
* that can be used later to remove the callback using
|
||||||
|
* rte_cryptodev_remove_enq_callback().
|
||||||
|
*
|
||||||
|
* Callbacks registered by application would not survive
|
||||||
|
* rte_cryptodev_configure() as it reinitializes the callback list.
|
||||||
|
* It is user responsibility to remove all installed callbacks before
|
||||||
|
* calling rte_cryptodev_configure() to avoid possible memory leakage.
|
||||||
|
* Application is expected to call add API after rte_cryptodev_configure().
|
||||||
|
*
|
||||||
|
* Multiple functions can be registered per queue pair & they are called
|
||||||
|
* in the order they were added. The API does not restrict on maximum number
|
||||||
|
* of callbacks.
|
||||||
|
*
|
||||||
|
* @param dev_id The identifier of the device.
|
||||||
|
* @param qp_id The index of the queue pair on which ops are
|
||||||
|
* to be enqueued for processing. The value
|
||||||
|
* must be in the range [0, nb_queue_pairs - 1]
|
||||||
|
* previously supplied to
|
||||||
|
* *rte_cryptodev_configure*.
|
||||||
|
* @param cb_fn The callback function
|
||||||
|
* @param cb_arg A generic pointer parameter which will be passed
|
||||||
|
* to each invocation of the callback function on
|
||||||
|
* this crypto device and queue pair.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - NULL on error & rte_errno will contain the error code.
|
||||||
|
* - On success, a pointer value which can later be used to remove the
|
||||||
|
* callback.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__rte_experimental
|
||||||
|
struct rte_cryptodev_cb *
|
||||||
|
rte_cryptodev_add_enq_callback(uint8_t dev_id,
|
||||||
|
uint16_t qp_id,
|
||||||
|
rte_cryptodev_callback_fn cb_fn,
|
||||||
|
void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a user callback function for given crypto device and queue pair.
|
||||||
|
*
|
||||||
|
* This function is used to remove enqueue callbacks that were added to a
|
||||||
|
* crypto device queue pair using rte_cryptodev_add_enq_callback().
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param dev_id The identifier of the device.
|
||||||
|
* @param qp_id The index of the queue pair on which ops are
|
||||||
|
* to be enqueued. The value must be in the
|
||||||
|
* range [0, nb_queue_pairs - 1] previously
|
||||||
|
* supplied to *rte_cryptodev_configure*.
|
||||||
|
* @param cb Pointer to user supplied callback created via
|
||||||
|
* rte_cryptodev_add_enq_callback().
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - 0: Success. Callback was removed.
|
||||||
|
* - <0: The dev_id or the qp_id is out of range, or the callback
|
||||||
|
* is NULL or not found for the crypto device queue pair.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__rte_experimental
|
||||||
|
int rte_cryptodev_remove_enq_callback(uint8_t dev_id,
|
||||||
|
uint16_t qp_id,
|
||||||
|
struct rte_cryptodev_cb *cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a user callback for a given crypto device and queue pair which will be
|
||||||
|
* called on crypto ops dequeue.
|
||||||
|
*
|
||||||
|
* This API configures a function to be called for each burst of crypto ops
|
||||||
|
* received on a given crypto device queue pair. The return value is a pointer
|
||||||
|
* that can be used later to remove the callback using
|
||||||
|
* rte_cryptodev_remove_deq_callback().
|
||||||
|
*
|
||||||
|
* Callbacks registered by application would not survive
|
||||||
|
* rte_cryptodev_configure() as it reinitializes the callback list.
|
||||||
|
* It is user responsibility to remove all installed callbacks before
|
||||||
|
* calling rte_cryptodev_configure() to avoid possible memory leakage.
|
||||||
|
* Application is expected to call add API after rte_cryptodev_configure().
|
||||||
|
*
|
||||||
|
* Multiple functions can be registered per queue pair & they are called
|
||||||
|
* in the order they were added. The API does not restrict on maximum number
|
||||||
|
* of callbacks.
|
||||||
|
*
|
||||||
|
* @param dev_id The identifier of the device.
|
||||||
|
* @param qp_id The index of the queue pair on which ops are
|
||||||
|
* to be dequeued. The value must be in the
|
||||||
|
* range [0, nb_queue_pairs - 1] previously
|
||||||
|
* supplied to *rte_cryptodev_configure*.
|
||||||
|
* @param cb_fn The callback function
|
||||||
|
* @param cb_arg A generic pointer parameter which will be passed
|
||||||
|
* to each invocation of the callback function on
|
||||||
|
* this crypto device and queue pair.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - NULL on error & rte_errno will contain the error code.
|
||||||
|
* - On success, a pointer value which can later be used to remove the
|
||||||
|
* callback.
|
||||||
|
*/
|
||||||
|
|
||||||
|
__rte_experimental
|
||||||
|
struct rte_cryptodev_cb *
|
||||||
|
rte_cryptodev_add_deq_callback(uint8_t dev_id,
|
||||||
|
uint16_t qp_id,
|
||||||
|
rte_cryptodev_callback_fn cb_fn,
|
||||||
|
void *cb_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a user callback function for given crypto device and queue pair.
|
||||||
|
*
|
||||||
|
* This function is used to remove dequeue callbacks that were added to a
|
||||||
|
* crypto device queue pair using rte_cryptodev_add_deq_callback().
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param dev_id The identifier of the device.
|
||||||
|
* @param qp_id The index of the queue pair on which ops are
|
||||||
|
* to be dequeued. The value must be in the
|
||||||
|
* range [0, nb_queue_pairs - 1] previously
|
||||||
|
* supplied to *rte_cryptodev_configure*.
|
||||||
|
* @param cb Pointer to user supplied callback created via
|
||||||
|
* rte_cryptodev_add_deq_callback().
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - 0: Success. Callback was removed.
|
||||||
|
* - <0: The dev_id or the qp_id is out of range, or the callback
|
||||||
|
* is NULL or not found for the crypto device queue pair.
|
||||||
|
*/
|
||||||
|
__rte_experimental
|
||||||
|
int rte_cryptodev_remove_deq_callback(uint8_t dev_id,
|
||||||
|
uint16_t qp_id,
|
||||||
|
struct rte_cryptodev_cb *cb);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -109,4 +109,11 @@ EXPERIMENTAL {
|
|||||||
rte_cryptodev_raw_enqueue;
|
rte_cryptodev_raw_enqueue;
|
||||||
rte_cryptodev_raw_enqueue_burst;
|
rte_cryptodev_raw_enqueue_burst;
|
||||||
rte_cryptodev_raw_enqueue_done;
|
rte_cryptodev_raw_enqueue_done;
|
||||||
|
|
||||||
|
# added in 21.02
|
||||||
|
rte_cryptodev_add_deq_callback;
|
||||||
|
rte_cryptodev_add_enq_callback;
|
||||||
|
rte_cryptodev_remove_deq_callback;
|
||||||
|
rte_cryptodev_remove_enq_callback;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user