dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2016-2020 Intel Corporation
   3 */
   4
   5#include <string.h>
   6
   7#include <rte_common.h>
   8#include <rte_malloc.h>
   9#include <rte_cryptodev_pmd.h>
  10
  11#include "aesni_gcm_pmd_private.h"
  12
  13static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[] = {
  14        {       /* AES GMAC (AUTH) */
  15                .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
  16                {.sym = {
  17                        .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
  18                        {.auth = {
  19                                .algo = RTE_CRYPTO_AUTH_AES_GMAC,
  20                                .block_size = 16,
  21                                .key_size = {
  22                                        .min = 16,
  23                                        .max = 32,
  24                                        .increment = 8
  25                                },
  26                                .digest_size = {
  27                                        .min = 1,
  28                                        .max = 16,
  29                                        .increment = 1
  30                                },
  31                                .iv_size = {
  32                                        .min = 12,
  33                                        .max = 12,
  34                                        .increment = 0
  35                                }
  36                        }, }
  37                }, }
  38        },
  39        {       /* AES GCM */
  40                .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
  41                {.sym = {
  42                        .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
  43                        {.aead = {
  44                                .algo = RTE_CRYPTO_AEAD_AES_GCM,
  45                                .block_size = 16,
  46                                .key_size = {
  47                                        .min = 16,
  48                                        .max = 32,
  49                                        .increment = 8
  50                                },
  51                                .digest_size = {
  52                                        .min = 1,
  53                                        .max = 16,
  54                                        .increment = 1
  55                                },
  56                                .aad_size = {
  57                                        .min = 0,
  58                                        .max = 65535,
  59                                        .increment = 1
  60                                },
  61                                .iv_size = {
  62                                        .min = 12,
  63                                        .max = 12,
  64                                        .increment = 0
  65                                }
  66                        }, }
  67                }, }
  68        },
  69        RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
  70};
  71
  72/** Configure device */
  73static int
  74aesni_gcm_pmd_config(__rte_unused struct rte_cryptodev *dev,
  75                __rte_unused struct rte_cryptodev_config *config)
  76{
  77        return 0;
  78}
  79
  80/** Start device */
  81static int
  82aesni_gcm_pmd_start(__rte_unused struct rte_cryptodev *dev)
  83{
  84        return 0;
  85}
  86
  87/** Stop device */
  88static void
  89aesni_gcm_pmd_stop(__rte_unused struct rte_cryptodev *dev)
  90{
  91}
  92
  93/** Close device */
  94static int
  95aesni_gcm_pmd_close(__rte_unused struct rte_cryptodev *dev)
  96{
  97        return 0;
  98}
  99
 100
 101/** Get device statistics */
 102static void
 103aesni_gcm_pmd_stats_get(struct rte_cryptodev *dev,
 104                struct rte_cryptodev_stats *stats)
 105{
 106        int qp_id;
 107
 108        for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
 109                struct aesni_gcm_qp *qp = dev->data->queue_pairs[qp_id];
 110
 111                stats->enqueued_count += qp->qp_stats.enqueued_count;
 112                stats->dequeued_count += qp->qp_stats.dequeued_count;
 113
 114                stats->enqueue_err_count += qp->qp_stats.enqueue_err_count;
 115                stats->dequeue_err_count += qp->qp_stats.dequeue_err_count;
 116        }
 117}
 118
 119/** Reset device statistics */
 120static void
 121aesni_gcm_pmd_stats_reset(struct rte_cryptodev *dev)
 122{
 123        int qp_id;
 124
 125        for (qp_id = 0; qp_id < dev->data->nb_queue_pairs; qp_id++) {
 126                struct aesni_gcm_qp *qp = dev->data->queue_pairs[qp_id];
 127
 128                memset(&qp->qp_stats, 0, sizeof(qp->qp_stats));
 129        }
 130}
 131
 132
 133/** Get device info */
 134static void
 135aesni_gcm_pmd_info_get(struct rte_cryptodev *dev,
 136                struct rte_cryptodev_info *dev_info)
 137{
 138        struct aesni_gcm_private *internals = dev->data->dev_private;
 139
 140        if (dev_info != NULL) {
 141                dev_info->driver_id = dev->driver_id;
 142                dev_info->feature_flags = dev->feature_flags;
 143                dev_info->capabilities = aesni_gcm_pmd_capabilities;
 144
 145                dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 146                /* No limit of number of sessions */
 147                dev_info->sym.max_nb_sessions = 0;
 148        }
 149}
 150
 151/** Release queue pair */
 152static int
 153aesni_gcm_pmd_qp_release(struct rte_cryptodev *dev, uint16_t qp_id)
 154{
 155        if (dev->data->queue_pairs[qp_id] != NULL) {
 156                struct aesni_gcm_qp *qp = dev->data->queue_pairs[qp_id];
 157
 158                if (qp->processed_pkts)
 159                        rte_ring_free(qp->processed_pkts);
 160
 161                rte_free(dev->data->queue_pairs[qp_id]);
 162                dev->data->queue_pairs[qp_id] = NULL;
 163        }
 164        return 0;
 165}
 166
 167/** set a unique name for the queue pair based on it's name, dev_id and qp_id */
 168static int
 169aesni_gcm_pmd_qp_set_unique_name(struct rte_cryptodev *dev,
 170                struct aesni_gcm_qp *qp)
 171{
 172        unsigned n = snprintf(qp->name, sizeof(qp->name),
 173                        "aesni_gcm_pmd_%u_qp_%u",
 174                        dev->data->dev_id, qp->id);
 175
 176        if (n >= sizeof(qp->name))
 177                return -1;
 178
 179        return 0;
 180}
 181
 182/** Create a ring to place process packets on */
 183static struct rte_ring *
 184aesni_gcm_pmd_qp_create_processed_pkts_ring(struct aesni_gcm_qp *qp,
 185                unsigned ring_size, int socket_id)
 186{
 187        struct rte_ring *r;
 188
 189        r = rte_ring_lookup(qp->name);
 190        if (r) {
 191                if (rte_ring_get_size(r) >= ring_size) {
 192                        AESNI_GCM_LOG(INFO, "Reusing existing ring %s for processed"
 193                                " packets", qp->name);
 194                        return r;
 195                }
 196                AESNI_GCM_LOG(ERR, "Unable to reuse existing ring %s for processed"
 197                                " packets", qp->name);
 198                return NULL;
 199        }
 200
 201        return rte_ring_create(qp->name, ring_size, socket_id,
 202                        RING_F_SP_ENQ | RING_F_SC_DEQ);
 203}
 204
 205/** Setup a queue pair */
 206static int
 207aesni_gcm_pmd_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
 208                const struct rte_cryptodev_qp_conf *qp_conf,
 209                int socket_id)
 210{
 211        struct aesni_gcm_qp *qp = NULL;
 212        struct aesni_gcm_private *internals = dev->data->dev_private;
 213
 214        /* Free memory prior to re-allocation if needed. */
 215        if (dev->data->queue_pairs[qp_id] != NULL)
 216                aesni_gcm_pmd_qp_release(dev, qp_id);
 217
 218        /* Allocate the queue pair data structure. */
 219        qp = rte_zmalloc_socket("AES-NI PMD Queue Pair", sizeof(*qp),
 220                                        RTE_CACHE_LINE_SIZE, socket_id);
 221        if (qp == NULL)
 222                return (-ENOMEM);
 223
 224        qp->id = qp_id;
 225        dev->data->queue_pairs[qp_id] = qp;
 226
 227        if (aesni_gcm_pmd_qp_set_unique_name(dev, qp))
 228                goto qp_setup_cleanup;
 229
 230        qp->ops = (const struct aesni_gcm_ops *)internals->ops;
 231
 232        qp->processed_pkts = aesni_gcm_pmd_qp_create_processed_pkts_ring(qp,
 233                        qp_conf->nb_descriptors, socket_id);
 234        if (qp->processed_pkts == NULL)
 235                goto qp_setup_cleanup;
 236
 237        qp->sess_mp = qp_conf->mp_session;
 238        qp->sess_mp_priv = qp_conf->mp_session_private;
 239
 240        memset(&qp->qp_stats, 0, sizeof(qp->qp_stats));
 241
 242        return 0;
 243
 244qp_setup_cleanup:
 245        if (qp)
 246                rte_free(qp);
 247
 248        return -1;
 249}
 250
 251/** Returns the size of the aesni gcm session structure */
 252static unsigned
 253aesni_gcm_pmd_sym_session_get_size(struct rte_cryptodev *dev __rte_unused)
 254{
 255        return sizeof(struct aesni_gcm_session);
 256}
 257
 258/** Configure a aesni gcm session from a crypto xform chain */
 259static int
 260aesni_gcm_pmd_sym_session_configure(struct rte_cryptodev *dev __rte_unused,
 261                struct rte_crypto_sym_xform *xform,
 262                struct rte_cryptodev_sym_session *sess,
 263                struct rte_mempool *mempool)
 264{
 265        void *sess_private_data;
 266        int ret;
 267        struct aesni_gcm_private *internals = dev->data->dev_private;
 268
 269        if (unlikely(sess == NULL)) {
 270                AESNI_GCM_LOG(ERR, "invalid session struct");
 271                return -EINVAL;
 272        }
 273
 274        if (rte_mempool_get(mempool, &sess_private_data)) {
 275                AESNI_GCM_LOG(ERR,
 276                                "Couldn't get object from session mempool");
 277                return -ENOMEM;
 278        }
 279        ret = aesni_gcm_set_session_parameters(internals->ops,
 280                                sess_private_data, xform);
 281        if (ret != 0) {
 282                AESNI_GCM_LOG(ERR, "failed configure session parameters");
 283
 284                /* Return session to mempool */
 285                rte_mempool_put(mempool, sess_private_data);
 286                return ret;
 287        }
 288
 289        set_sym_session_private_data(sess, dev->driver_id,
 290                        sess_private_data);
 291
 292        return 0;
 293}
 294
 295/** Clear the memory of session so it doesn't leave key material behind */
 296static void
 297aesni_gcm_pmd_sym_session_clear(struct rte_cryptodev *dev,
 298                struct rte_cryptodev_sym_session *sess)
 299{
 300        uint8_t index = dev->driver_id;
 301        void *sess_priv = get_sym_session_private_data(sess, index);
 302
 303        /* Zero out the whole structure */
 304        if (sess_priv) {
 305                memset(sess_priv, 0, sizeof(struct aesni_gcm_session));
 306                struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
 307                set_sym_session_private_data(sess, index, NULL);
 308                rte_mempool_put(sess_mp, sess_priv);
 309        }
 310}
 311
 312struct rte_cryptodev_ops aesni_gcm_pmd_ops = {
 313                .dev_configure          = aesni_gcm_pmd_config,
 314                .dev_start              = aesni_gcm_pmd_start,
 315                .dev_stop               = aesni_gcm_pmd_stop,
 316                .dev_close              = aesni_gcm_pmd_close,
 317
 318                .stats_get              = aesni_gcm_pmd_stats_get,
 319                .stats_reset            = aesni_gcm_pmd_stats_reset,
 320
 321                .dev_infos_get          = aesni_gcm_pmd_info_get,
 322
 323                .queue_pair_setup       = aesni_gcm_pmd_qp_setup,
 324                .queue_pair_release     = aesni_gcm_pmd_qp_release,
 325
 326                .sym_cpu_process        = aesni_gcm_pmd_cpu_crypto_process,
 327
 328                .sym_session_get_size   = aesni_gcm_pmd_sym_session_get_size,
 329                .sym_session_configure  = aesni_gcm_pmd_sym_session_configure,
 330                .sym_session_clear      = aesni_gcm_pmd_sym_session_clear
 331};
 332
 333struct rte_cryptodev_ops *rte_aesni_gcm_pmd_ops = &aesni_gcm_pmd_ops;
 334