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