kvargs: promote delimited parsing as stable
[dpdk.git] / drivers / crypto / mvsam / rte_mrvl_pmd_ops.c
index d253b8f..3064b1f 100644 (file)
@@ -8,9 +8,10 @@
 
 #include <rte_common.h>
 #include <rte_malloc.h>
-#include <rte_cryptodev_pmd.h>
+#include <cryptodev_pmd.h>
+#include <rte_security_driver.h>
 
-#include "rte_mrvl_pmd_private.h"
+#include "mrvl_pmd_private.h"
 
 /**
  * Capabilities list to be used in reporting to DPDK.
@@ -111,7 +112,7 @@ static const struct rte_cryptodev_capabilities
                                        .increment = 1
                                },
                                .digest_size = {
-                                       .min = 28,
+                                       .min = 12,
                                        .max = 28,
                                        .increment = 0
                                },
@@ -232,7 +233,7 @@ static const struct rte_cryptodev_capabilities
                                },
                                .digest_size = {
                                        .min = 12,
-                                       .max = 48,
+                                       .max = 64,
                                        .increment = 4
                                },
                        }, }
@@ -252,7 +253,7 @@ static const struct rte_cryptodev_capabilities
                                },
                                .digest_size = {
                                        .min = 12,
-                                       .max = 48,
+                                       .max = 64,
                                        .increment = 0
                                },
                        }, }
@@ -298,6 +299,26 @@ static const struct rte_cryptodev_capabilities
                        }, }
                }, }
        },
+       {       /* AES ECB */
+               .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+               {.sym = {
+                       .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+                       {.cipher = {
+                               .algo = RTE_CRYPTO_CIPHER_AES_ECB,
+                               .block_size = 16,
+                               .key_size = {
+                                       .min = 16,
+                                       .max = 32,
+                                       .increment = 8
+                               },
+                               .iv_size = {
+                                       .min = 0,
+                                       .max = 0,
+                                       .increment = 0
+                               }
+                       }, }
+               }, }
+       },
        {       /* AES GCM */
                .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
                {.sym = {
@@ -316,9 +337,9 @@ static const struct rte_cryptodev_capabilities
                                        .increment = 0
                                },
                                .aad_size = {
-                                       .min = 8,
-                                       .max = 12,
-                                       .increment = 4
+                                       .min = 0,
+                                       .max = 64,
+                                       .increment = 1
                                },
                                .iv_size = {
                                        .min = 12,
@@ -393,6 +414,71 @@ static const struct rte_cryptodev_capabilities
                        }, }
                }, }
        },
+       {       /* 3DES ECB */
+               .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+               {.sym = {
+                       .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+                       {.cipher = {
+                               .algo = RTE_CRYPTO_CIPHER_3DES_ECB,
+                               .block_size = 8,
+                               .key_size = {
+                                       .min = 24,
+                                       .max = 24,
+                                       .increment = 0
+                               },
+                               .iv_size = {
+                                       .min = 0,
+                                       .max = 0,
+                                       .increment = 0
+                               }
+                       }, }
+               }, }
+       },
+       {       /* NULL (AUTH) */
+               .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+               {.sym = {
+                       .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+                       {.auth = {
+                               .algo = RTE_CRYPTO_AUTH_NULL,
+                               .block_size = 1,
+                               .key_size = {
+                                       .min = 0,
+                                       .max = 0,
+                                       .increment = 0
+                               },
+                               .digest_size = {
+                                       .min = 0,
+                                       .max = 0,
+                                       .increment = 0
+                               },
+                               .iv_size = {
+                                       .min = 0,
+                                       .max = 0,
+                                       .increment = 0
+                               }
+                       }, },
+               }, },
+       },
+       {       /* NULL (CIPHER) */
+               .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+               {.sym = {
+                       .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+                       {.cipher = {
+                               .algo = RTE_CRYPTO_CIPHER_NULL,
+                               .block_size = 1,
+                               .key_size = {
+                                       .min = 0,
+                                       .max = 0,
+                                       .increment = 0
+                               },
+                               .iv_size = {
+                                       .min = 0,
+                                       .max = 0,
+                                       .increment = 0
+                               }
+                       }, },
+               }, }
+       },
 
        RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
@@ -548,7 +634,7 @@ mrvl_crypto_pmd_close(struct rte_cryptodev *dev)
 static int
 mrvl_crypto_pmd_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
                const struct rte_cryptodev_qp_conf *qp_conf,
-               int socket_id, struct rte_mempool *session_pool)
+               int socket_id)
 {
        struct mrvl_crypto_qp *qp = NULL;
        char match[RTE_CRYPTODEV_NAME_MAX_LEN];
@@ -572,11 +658,16 @@ mrvl_crypto_pmd_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
                 */
                int num = sam_get_num_inst();
                if (num == 0) {
-                       MRVL_CRYPTO_LOG_ERR("No crypto engines detected.\n");
+                       MRVL_LOG(ERR, "No crypto engines detected!");
                        return -1;
                }
 
                /*
+                * In case just one engine is enabled mapping will look as
+                * follows:
+                * qp:      0        1        2        3
+                * cio-x:y: cio-0:0, cio-0:1, cio-0:2, cio-0:3
+                *
                 * In case two crypto engines are enabled qps will
                 * be evenly spread among them. Even and odd qps will
                 * be handled by cio-0 and cio-1 respectively. qp-cio mapping
@@ -588,10 +679,17 @@ mrvl_crypto_pmd_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
                 * qp:      4        5        6        7
                 * cio-x:y: cio-0:2, cio-1:2, cio-0:3, cio-1:3
                 *
-                * In case just one engine is enabled mapping will look as
-                * follows:
+                * In case of three crypto engines are enabled qps will
+                * be mapped as following:
+                *
                 * qp:      0        1        2        3
-                * cio-x:y: cio-0:0, cio-0:1, cio-0:2, cio-0:3
+                * cio-x:y: cio-0:0, cio-1:0, cio-2:0, cio-0:1
+                *
+                * qp:      4        5        6        7
+                * cio-x:y: cio-1:1, cio-2:1, cio-0:2, cio-1:2
+                *
+                * qp:      8        9        10       11
+                * cio-x:y: cio-2:2, cio-0:3, cio-1:3, cio-2:3
                 */
                n = snprintf(match, sizeof(match), "cio-%u:%u",
                                qp_id % num, qp_id / num);
@@ -605,7 +703,8 @@ mrvl_crypto_pmd_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
                if (sam_cio_init(&qp->cio_params, &qp->cio) < 0)
                        break;
 
-               qp->sess_mp = session_pool;
+               qp->sess_mp = qp_conf->mp_session;
+               qp->sess_mp_priv = qp_conf->mp_session_private;
 
                memset(&qp->stats, 0, sizeof(qp->stats));
                dev->data->queue_pairs[qp_id] = qp;
@@ -616,17 +715,6 @@ mrvl_crypto_pmd_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
        return -1;
 }
 
-/** Return the number of allocated queue pairs (PMD ops callback).
- *
- * @param dev Pointer to the device structure.
- * @returns Number of allocated queue pairs.
- */
-static uint32_t
-mrvl_crypto_pmd_qp_count(struct rte_cryptodev *dev)
-{
-       return dev->data->nb_queue_pairs;
-}
-
 /** Returns the size of the session structure (PMD ops callback).
  *
  * @param dev Pointer to the device structure [Unused].
@@ -641,7 +729,7 @@ mrvl_crypto_pmd_sym_session_get_size(__rte_unused struct rte_cryptodev *dev)
 /** Configure the session from a crypto xform chain (PMD ops callback).
  *
  * @param dev Pointer to the device structure.
- * @param xform Pointer to the crytpo configuration structure.
+ * @param xform Pointer to the crypto configuration structure.
  * @param sess Pointer to the empty session structure.
  * @returns 0 upon success, negative value otherwise.
  */
@@ -656,7 +744,7 @@ mrvl_crypto_pmd_sym_session_configure(__rte_unused struct rte_cryptodev *dev,
        int ret;
 
        if (sess == NULL) {
-               MRVL_CRYPTO_LOG_ERR("Invalid session struct.");
+               MRVL_LOG(ERR, "Invalid session struct!");
                return -EINVAL;
        }
 
@@ -665,9 +753,11 @@ mrvl_crypto_pmd_sym_session_configure(__rte_unused struct rte_cryptodev *dev,
                return -ENOMEM;
        }
 
+       memset(sess_private_data, 0, sizeof(struct mrvl_crypto_session));
+
        ret = mrvl_crypto_set_session_parameters(sess_private_data, xform);
        if (ret != 0) {
-               MRVL_CRYPTO_LOG_ERR("Failed to configure session parameters.");
+               MRVL_LOG(ERR, "Failed to configure session parameters!");
 
                /* Return session to mempool */
                rte_mempool_put(mp, sess_private_data);
@@ -679,10 +769,16 @@ mrvl_crypto_pmd_sym_session_configure(__rte_unused struct rte_cryptodev *dev,
        mrvl_sess = (struct mrvl_crypto_session *)sess_private_data;
        if (sam_session_create(&mrvl_sess->sam_sess_params,
                                &mrvl_sess->sam_sess) < 0) {
-               MRVL_CRYPTO_LOG_DBG("Failed to create session!");
+               MRVL_LOG(DEBUG, "Failed to create session!");
                return -EIO;
        }
 
+       /* free the keys memory allocated for session creation */
+       if (mrvl_sess->sam_sess_params.cipher_key != NULL)
+               free(mrvl_sess->sam_sess_params.cipher_key);
+       if (mrvl_sess->sam_sess_params.auth_key != NULL)
+               free(mrvl_sess->sam_sess_params.auth_key);
+
        return 0;
 }
 
@@ -707,10 +803,10 @@ mrvl_crypto_pmd_sym_session_clear(struct rte_cryptodev *dev,
 
                if (mrvl_sess->sam_sess &&
                    sam_session_destroy(mrvl_sess->sam_sess) < 0) {
-                       MRVL_CRYPTO_LOG_INFO("Error while destroying session!");
+                       MRVL_LOG(ERR, "Error while destroying session!");
                }
 
-               memset(sess, 0, sizeof(struct mrvl_crypto_session));
+               memset(mrvl_sess, 0, sizeof(struct mrvl_crypto_session));
                struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
                set_sym_session_private_data(sess, index, NULL);
                rte_mempool_put(sess_mp, sess_priv);
@@ -733,7 +829,6 @@ static struct rte_cryptodev_ops mrvl_crypto_pmd_ops = {
 
                .queue_pair_setup       = mrvl_crypto_pmd_qp_setup,
                .queue_pair_release     = mrvl_crypto_pmd_qp_release,
-               .queue_pair_count       = mrvl_crypto_pmd_qp_count,
 
                .sym_session_get_size   = mrvl_crypto_pmd_sym_session_get_size,
                .sym_session_configure  = mrvl_crypto_pmd_sym_session_configure,
@@ -741,3 +836,177 @@ static struct rte_cryptodev_ops mrvl_crypto_pmd_ops = {
 };
 
 struct rte_cryptodev_ops *rte_mrvl_crypto_pmd_ops = &mrvl_crypto_pmd_ops;
+
+/* IPSEC full offloading */
+
+/** Configure the session from a crypto xform chain (PMD ops callback).
+ *
+ * @param dev Pointer to the device structure.
+ * @param conf Pointer to the security session configuration structure.
+ * @param sess Pointer to the empty session structure.
+ * @param mempool Pointer to memory pool.
+ * @returns 0 upon success, negative value otherwise.
+ */
+static int
+mrvl_crypto_pmd_security_session_create(__rte_unused void *dev,
+                                struct rte_security_session_conf *conf,
+                                struct rte_security_session *sess,
+                                struct rte_mempool *mempool)
+{
+       struct mrvl_crypto_session *mrvl_sess;
+       void *sess_private_data;
+       int ret;
+
+       if (sess == NULL) {
+               MRVL_LOG(ERR, "Invalid session struct.");
+               return -EINVAL;
+       }
+
+       if (rte_mempool_get(mempool, &sess_private_data)) {
+               MRVL_LOG(ERR, "Couldn't get object from session mempool.");
+               return -ENOMEM;
+       }
+
+       switch (conf->protocol) {
+       case RTE_SECURITY_PROTOCOL_IPSEC:
+               mrvl_sess = (struct mrvl_crypto_session *)sess_private_data;
+
+               struct rte_security_ipsec_xform *ipsec_xform = &conf->ipsec;
+               struct rte_crypto_sym_xform *crypto_xform = conf->crypto_xform;
+
+               ret = mrvl_ipsec_set_session_parameters(mrvl_sess,
+                                                       ipsec_xform,
+                                                       crypto_xform);
+               if (ret != 0) {
+                       MRVL_LOG(ERR, "Failed to configure session parameters.");
+
+                       /* Return session to mempool */
+                       rte_mempool_put(mempool, sess_private_data);
+                       return ret;
+               }
+
+               if (mrvl_sess->sam_sess_params.cipher_mode == SAM_CIPHER_GCM) {
+                       /* Nonce is must for all counter modes */
+                       mrvl_sess->sam_sess_params.cipher_iv =
+                               (uint8_t *)&(conf->ipsec.salt);
+               }
+
+               ret = sam_session_create(&mrvl_sess->sam_sess_params,
+                               &mrvl_sess->sam_sess);
+               if (ret < 0) {
+                       MRVL_LOG(ERR, "PMD: failed to create IPSEC session.");
+                       /* Return session to mempool */
+                       rte_mempool_put(mempool, sess_private_data);
+                       return ret;
+               }
+               break;
+       case RTE_SECURITY_PROTOCOL_MACSEC:
+               return -ENOTSUP;
+       default:
+               return -EINVAL;
+       }
+
+       set_sec_session_private_data(sess, sess_private_data);
+
+       return ret;
+}
+
+/** Clear the memory of session so it doesn't leave key material behind */
+static int
+mrvl_crypto_pmd_security_session_destroy(void *dev __rte_unused,
+               struct rte_security_session *sess)
+{
+       void *sess_priv = get_sec_session_private_data(sess);
+
+       /* Zero out the whole structure */
+       if (sess_priv) {
+               struct mrvl_crypto_session *mrvl_sess =
+                       (struct mrvl_crypto_session *)sess_priv;
+               struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
+
+               if (mrvl_sess->sam_sess &&
+                   sam_session_destroy(mrvl_sess->sam_sess) < 0) {
+                       MRVL_LOG(ERR, "Error while destroying session!");
+               }
+
+               rte_free(mrvl_sess->sam_sess_params.cipher_key);
+               rte_free(mrvl_sess->sam_sess_params.auth_key);
+               rte_free(mrvl_sess->sam_sess_params.cipher_iv);
+               memset(sess, 0, sizeof(struct rte_security_session));
+               set_sec_session_private_data(sess, NULL);
+               rte_mempool_put(sess_mp, sess_priv);
+       }
+       return 0;
+}
+
+static const
+struct rte_security_capability mrvl_crypto_pmd_sec_security_cap[] = {
+       { /* IPsec Lookaside Protocol offload ESP Tunnel Egress */
+               .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+               .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+               .ipsec = {
+                       .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+                       .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+                       .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+                       .options = { 0 },
+                       .replay_win_sz_max = 128
+               },
+               .crypto_capabilities = mrvl_crypto_pmd_capabilities
+       },
+       { /* IPsec Lookaside Protocol offload ESP Tunnel Ingress */
+               .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+               .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+               .ipsec = {
+                       .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+                       .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+                       .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+                       .options = { 0 },
+                       .replay_win_sz_max = 128
+               },
+               .crypto_capabilities = mrvl_crypto_pmd_capabilities
+       },
+       { /* IPsec Lookaside Protocol offload ESP Transport Egress */
+               .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+               .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+               .ipsec = {
+                       .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+                       .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+                       .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+                       .options = { 0 },
+                       .replay_win_sz_max = 128
+               },
+               .crypto_capabilities = mrvl_crypto_pmd_capabilities
+       },
+       { /* IPsec Lookaside Protocol offload ESP Transport Ingress */
+               .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+               .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+               .ipsec = {
+                       .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
+                       .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+                       .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+                       .options = { 0 },
+                       .replay_win_sz_max = 128
+               },
+               .crypto_capabilities = mrvl_crypto_pmd_capabilities
+       },
+       {
+               .action = RTE_SECURITY_ACTION_TYPE_NONE
+       }
+};
+
+static const struct rte_security_capability *
+mrvl_crypto_pmd_security_capabilities_get(void *device __rte_unused)
+{
+       return mrvl_crypto_pmd_sec_security_cap;
+}
+
+struct rte_security_ops mrvl_sec_security_pmd_ops = {
+       .session_create = mrvl_crypto_pmd_security_session_create,
+       .session_update = NULL,
+       .session_stats_get = NULL,
+       .session_destroy = mrvl_crypto_pmd_security_session_destroy,
+       .set_pkt_metadata = NULL,
+       .capabilities_get = mrvl_crypto_pmd_security_capabilities_get
+};
+
+struct rte_security_ops *rte_mrvl_security_pmd_ops = &mrvl_sec_security_pmd_ops;