+static struct qman_fq *
+dpaa_sec_attach_rxq(struct dpaa_sec_dev_private *qi)
+{
+ unsigned int i;
+
+ for (i = 0; i < RTE_DPAA_MAX_RX_QUEUE; i++) {
+ if (qi->inq_attach[i] == 0) {
+ qi->inq_attach[i] = 1;
+ return &qi->inq[i];
+ }
+ }
+ DPAA_SEC_WARN("All session in use %u", qi->max_nb_sessions);
+
+ return NULL;
+}
+
+static int
+dpaa_sec_detach_rxq(struct dpaa_sec_dev_private *qi, struct qman_fq *fq)
+{
+ unsigned int i;
+
+ for (i = 0; i < RTE_DPAA_MAX_RX_QUEUE; i++) {
+ if (&qi->inq[i] == fq) {
+ if (qman_retire_fq(fq, NULL) != 0)
+ DPAA_SEC_WARN("Queue is not retired\n");
+ qman_oos_fq(fq);
+ qi->inq_attach[i] = 0;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int
+dpaa_sec_attach_sess_q(struct dpaa_sec_qp *qp, dpaa_sec_session *sess)
+{
+ int ret;
+
+ sess->qp[rte_lcore_id() % MAX_DPAA_CORES] = qp;
+ ret = dpaa_sec_prep_cdb(sess);
+ if (ret) {
+ DPAA_SEC_ERR("Unable to prepare sec cdb");
+ return -1;
+ }
+ if (unlikely(!RTE_PER_LCORE(dpaa_io))) {
+ ret = rte_dpaa_portal_init((void *)0);
+ if (ret) {
+ DPAA_SEC_ERR("Failure in affining portal");
+ return ret;
+ }
+ }
+ ret = dpaa_sec_init_rx(sess->inq[rte_lcore_id() % MAX_DPAA_CORES],
+ rte_dpaa_mem_vtop(&sess->cdb),
+ qman_fq_fqid(&qp->outq));
+ if (ret)
+ DPAA_SEC_ERR("Unable to init sec queue");
+
+ return ret;
+}
+
+static int
+dpaa_sec_set_session_parameters(struct rte_cryptodev *dev,
+ struct rte_crypto_sym_xform *xform, void *sess)
+{
+ struct dpaa_sec_dev_private *internals = dev->data->dev_private;
+ dpaa_sec_session *session = sess;
+ uint32_t i;
+ int ret;
+
+ PMD_INIT_FUNC_TRACE();
+
+ if (unlikely(sess == NULL)) {
+ DPAA_SEC_ERR("invalid session struct");
+ return -EINVAL;
+ }
+ memset(session, 0, sizeof(dpaa_sec_session));
+
+ /* Default IV length = 0 */
+ session->iv.length = 0;
+
+ /* Cipher Only */
+ if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER && xform->next == NULL) {
+ session->auth_alg = RTE_CRYPTO_AUTH_NULL;
+ ret = dpaa_sec_cipher_init(dev, xform, session);
+
+ /* Authentication Only */
+ } else if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
+ xform->next == NULL) {
+ session->cipher_alg = RTE_CRYPTO_CIPHER_NULL;
+ session->ctxt = DPAA_SEC_AUTH;
+ ret = dpaa_sec_auth_init(dev, xform, session);
+
+ /* Cipher then Authenticate */
+ } else if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+ xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
+ if (xform->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT) {
+ session->auth_cipher_text = 1;
+ if (xform->cipher.algo == RTE_CRYPTO_CIPHER_NULL)
+ ret = dpaa_sec_auth_init(dev, xform, session);
+ else if (xform->next->auth.algo == RTE_CRYPTO_AUTH_NULL)
+ ret = dpaa_sec_cipher_init(dev, xform, session);
+ else
+ ret = dpaa_sec_chain_init(dev, xform, session);
+ } else {
+ DPAA_SEC_ERR("Not supported: Auth then Cipher");
+ return -EINVAL;
+ }
+ /* Authenticate then Cipher */
+ } else if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH &&
+ xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+ if (xform->next->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
+ session->auth_cipher_text = 0;
+ if (xform->auth.algo == RTE_CRYPTO_AUTH_NULL)
+ ret = dpaa_sec_cipher_init(dev, xform, session);
+ else if (xform->next->cipher.algo
+ == RTE_CRYPTO_CIPHER_NULL)
+ ret = dpaa_sec_auth_init(dev, xform, session);
+ else
+ ret = dpaa_sec_chain_init(dev, xform, session);
+ } else {
+ DPAA_SEC_ERR("Not supported: Auth then Cipher");
+ return -EINVAL;
+ }
+
+ /* AEAD operation for AES-GCM kind of Algorithms */
+ } else if (xform->type == RTE_CRYPTO_SYM_XFORM_AEAD &&
+ xform->next == NULL) {
+ ret = dpaa_sec_aead_init(dev, xform, session);
+
+ } else {
+ DPAA_SEC_ERR("Invalid crypto type");
+ return -EINVAL;
+ }
+ if (ret) {
+ DPAA_SEC_ERR("unable to init session");
+ goto err1;
+ }
+
+ rte_spinlock_lock(&internals->lock);
+ for (i = 0; i < MAX_DPAA_CORES; i++) {
+ session->inq[i] = dpaa_sec_attach_rxq(internals);
+ if (session->inq[i] == NULL) {
+ DPAA_SEC_ERR("unable to attach sec queue");
+ rte_spinlock_unlock(&internals->lock);
+ goto err1;
+ }
+ }
+ rte_spinlock_unlock(&internals->lock);
+
+ return 0;
+
+err1:
+ rte_free(session->cipher_key.data);
+ rte_free(session->auth_key.data);
+ memset(session, 0, sizeof(dpaa_sec_session));
+
+ return -EINVAL;
+}
+
+static int
+dpaa_sec_sym_session_configure(struct rte_cryptodev *dev,
+ struct rte_crypto_sym_xform *xform,
+ struct rte_cryptodev_sym_session *sess,
+ struct rte_mempool *mempool)
+{
+ void *sess_private_data;
+ int ret;
+
+ PMD_INIT_FUNC_TRACE();
+
+ if (rte_mempool_get(mempool, &sess_private_data)) {
+ DPAA_SEC_ERR("Couldn't get object from session mempool");
+ return -ENOMEM;
+ }
+
+ ret = dpaa_sec_set_session_parameters(dev, xform, sess_private_data);
+ if (ret != 0) {
+ DPAA_SEC_ERR("failed to configure session parameters");
+
+ /* Return session to mempool */
+ rte_mempool_put(mempool, sess_private_data);
+ return ret;
+ }
+
+ set_sym_session_private_data(sess, dev->driver_id,
+ sess_private_data);
+
+
+ return 0;
+}
+
+static inline void
+free_session_memory(struct rte_cryptodev *dev, dpaa_sec_session *s)
+{
+ struct dpaa_sec_dev_private *qi = dev->data->dev_private;
+ struct rte_mempool *sess_mp = rte_mempool_from_obj((void *)s);
+ uint8_t i;
+
+ for (i = 0; i < MAX_DPAA_CORES; i++) {
+ if (s->inq[i])
+ dpaa_sec_detach_rxq(qi, s->inq[i]);
+ s->inq[i] = NULL;
+ s->qp[i] = NULL;
+ }
+ rte_free(s->cipher_key.data);
+ rte_free(s->auth_key.data);
+ memset(s, 0, sizeof(dpaa_sec_session));
+ rte_mempool_put(sess_mp, (void *)s);
+}
+
+/** Clear the memory of session so it doesn't leave key material behind */
+static void
+dpaa_sec_sym_session_clear(struct rte_cryptodev *dev,
+ struct rte_cryptodev_sym_session *sess)
+{
+ PMD_INIT_FUNC_TRACE();
+ uint8_t index = dev->driver_id;
+ void *sess_priv = get_sym_session_private_data(sess, index);
+ dpaa_sec_session *s = (dpaa_sec_session *)sess_priv;
+
+ if (sess_priv) {
+ free_session_memory(dev, s);
+ set_sym_session_private_data(sess, index, NULL);
+ }
+}
+
+#ifdef RTE_LIBRTE_SECURITY
+static int
+dpaa_sec_ipsec_aead_init(struct rte_crypto_aead_xform *aead_xform,
+ struct rte_security_ipsec_xform *ipsec_xform,
+ dpaa_sec_session *session)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ session->aead_key.data = rte_zmalloc(NULL, aead_xform->key.length,
+ RTE_CACHE_LINE_SIZE);
+ if (session->aead_key.data == NULL && aead_xform->key.length > 0) {
+ DPAA_SEC_ERR("No Memory for aead key");
+ return -1;
+ }
+ memcpy(session->aead_key.data, aead_xform->key.data,
+ aead_xform->key.length);
+
+ session->digest_length = aead_xform->digest_length;
+ session->aead_key.length = aead_xform->key.length;
+
+ switch (aead_xform->algo) {
+ case RTE_CRYPTO_AEAD_AES_GCM:
+ switch (session->digest_length) {
+ case 8:
+ session->aead_key.alg = OP_PCL_IPSEC_AES_GCM8;
+ break;
+ case 12:
+ session->aead_key.alg = OP_PCL_IPSEC_AES_GCM12;
+ break;
+ case 16:
+ session->aead_key.alg = OP_PCL_IPSEC_AES_GCM16;
+ break;
+ default:
+ DPAA_SEC_ERR("Crypto: Undefined GCM digest %d",
+ session->digest_length);
+ return -1;
+ }
+ if (session->dir == DIR_ENC) {
+ memcpy(session->encap_pdb.gcm.salt,
+ (uint8_t *)&(ipsec_xform->salt), 4);
+ } else {
+ memcpy(session->decap_pdb.gcm.salt,
+ (uint8_t *)&(ipsec_xform->salt), 4);
+ }
+ session->aead_key.algmode = OP_ALG_AAI_GCM;
+ session->aead_alg = RTE_CRYPTO_AEAD_AES_GCM;
+ break;
+ default:
+ DPAA_SEC_ERR("Crypto: Undefined AEAD specified %u",
+ aead_xform->algo);
+ return -1;
+ }
+ return 0;
+}
+