Proposed changes to cryptodev API for comment based on Neil's comments
on the initial RFC. I have included the updates to the cryptodev unit test
suite and the AESNI multi buffer PMD for illustrative purposes, I will include 
the
changes for the QAT in a V1 patchset if the proposes changes to the API are
acceptable.

Signed-off-by: Declan Doherty <declan.doherty at intel.com>
---
 app/test/test_cryptodev.c                          | 276 +++++++++++++++------
 drivers/crypto/aesni_mb/aesni_mb_ops.h             |   2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c         | 188 +++++++++-----
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c     |  10 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h |  28 ++-
 lib/librte_cryptodev/rte_crypto.h                  | 141 ++++++++---
 lib/librte_cryptodev/rte_cryptodev.c               |  54 ++--
 lib/librte_cryptodev/rte_cryptodev.h               |  26 +-
 lib/librte_cryptodev/rte_cryptodev_pmd.h           |  10 +-
 9 files changed, 506 insertions(+), 229 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 68cc0bf..93b7e0a 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -62,6 +62,8 @@
 #define DIGEST_BYTE_LENGTH_SHA1                (BYTE_LENGTH(160))
 #define DIGEST_BYTE_LENGTH_SHA256      (BYTE_LENGTH(256))
 #define DIGEST_BYTE_LENGTH_SHA512      (BYTE_LENGTH(512))
+#define DIGEST_BYTE_LENGTH_AES_XCBC     (BYTE_LENGTH(96))
+#define AES_XCBC_MAC_KEY_SZ             (16)

 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA1              (12)
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA256            (16)
@@ -75,13 +77,13 @@ struct crypto_testsuite_params {
        struct rte_cryptodev_config conf;
        struct rte_cryptodev_qp_conf qp_conf;

-       uint8_t valid_devs[RTE_MAX_CRYPTODEVS];
+       uint8_t valid_devs[RTE_CRYPTO_MAX_DEVS];
        uint8_t valid_dev_count;
 };

 struct crypto_unittest_params {
-       struct rte_crypto_cipher_params cipher_params;
-       struct rte_crypto_hash_params hash_params;
+       struct rte_crypto_xform cipher_xform;
+       struct rte_crypto_xform auth_xform;

        struct rte_cryptodev_session *sess;

@@ -92,6 +94,17 @@ struct crypto_unittest_params {
        uint8_t *digest;
 };

+/*
+ * Forward declarations.
+ */
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(struct 
crypto_unittest_params *ut_params);
+
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_perform(struct rte_cryptodev_session *sess,
+               struct crypto_unittest_params *ut_params,
+               struct crypto_testsuite_params *ts_param);
+
 static struct rte_mbuf *
 setup_test_string(struct rte_mempool *mpool,
                const char *string, size_t len, uint8_t blocksize)
@@ -184,7 +197,7 @@ testsuite_setup(void)
        }

        ts_params->crypto_op_pool = rte_crypto_op_pool_create("CRYPTO_OP_POOL",
-                       NUM_MBUFS, MBUF_CACHE_SIZE, rte_socket_id());
+                       NUM_MBUFS, MBUF_CACHE_SIZE, 2, rte_socket_id());
        if (ts_params->crypto_op_pool == NULL) {
                RTE_LOG(ERR, USER1, "Can't create CRYPTO_OP_POOL\n");
                return TEST_FAILED;
@@ -436,6 +449,11 @@ static const uint8_t 
catch_22_quote_2_512_bytes_AES_CBC_ciphertext[] = {
        0X95, 0XBB, 0X26, 0X74, 0X69, 0X12, 0X7F, 0XF1, 0XBB, 0XFF, 0XAE, 0XB5, 
0X99, 0X6E, 0XCB, 0X0C
 };

+static const uint8_t catch_22_quote_2_512_bytes_AES_CBC_HMAC_SHA1_digest[] = {
+       0x9a, 0X4f, 0X88, 0X1b, 0Xb6, 0X8f, 0Xd8, 0X60,
+       0X42, 0X1a, 0X7d, 0X3d, 0Xf5, 0X82, 0X80, 0Xf1,
+       0X18, 0X8c, 0X1d, 0X32 };
+

 static int
 test_AES_CBC_HMAC_SHA1_encrypt_digest(void)
@@ -452,22 +470,28 @@ test_AES_CBC_HMAC_SHA1_encrypt_digest(void)
        TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");

        /* Setup Cipher Parameters */
-       ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-       ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
-       ut_params->cipher_params.key.data = aes_cbc_key;
-       ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+       ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+       ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+       ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+       ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
+       ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+       ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;

        /* Setup HMAC Parameters */
-       ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
-       ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
-       ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA1;
-       ut_params->hash_params.auth_key.data = hmac_sha1_key;
-       ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA1;
+
+       ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+       ut_params->auth_xform.next = NULL;
+
+       ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
+       ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
+       ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA1;
+       ut_params->auth_xform.auth.key.data = hmac_sha1_key;
+       ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA1;

        /* Create Crypto session*/
        ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-                       &ut_params->cipher_params, &ut_params->hash_params,
-                       RTE_CRYPTO_SYM_OPCHAIN_CIPHER_HASH);
+                       &ut_params->cipher_xform);
        TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");

        /* Generate Crypto op data structure */
@@ -522,6 +546,88 @@ test_AES_CBC_HMAC_SHA1_encrypt_digest(void)
        return TEST_SUCCESS;
 }

+
+static int
+test_AES_CBC_HMAC_SHA1_encrypt_digest_sessionless(void)
+{
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+       struct crypto_unittest_params *ut_params = &unittest_params;
+
+       /* Generate test mbuf data and space for digest */
+       ut_params->ibuf = setup_test_string(ts_params->mbuf_pool, 
catch_22_quote,
+                       QUOTE_512_BYTES, 0);
+
+       ut_params->digest = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+                       DIGEST_BYTE_LENGTH_SHA1);
+       TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");
+
+       /* Generate Crypto op data structure */
+       ut_params->op = 
rte_crypto_op_alloc_sessionless(ts_params->crypto_op_pool, 2);
+       TEST_ASSERT_NOT_NULL(ut_params->op, "Failed to allocate crypto_op");
+
+       /* Set crypto operation data parameters */
+       ut_params->op->xform->type = RTE_CRYPTO_XFORM_CIPHER;
+
+       /* cipher parameters */
+       ut_params->op->xform->cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
+       ut_params->op->xform->cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+       ut_params->op->xform->cipher.key.data = aes_cbc_key;
+       ut_params->op->xform->cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+
+       /* hash parameters */
+       ut_params->op->xform->next->type = RTE_CRYPTO_XFORM_AUTH;
+
+       ut_params->op->xform->next->auth.op = 
RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
+       ut_params->op->xform->next->auth.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
+       ut_params->op->xform->next->auth.key.length = HMAC_KEY_LENGTH_SHA1;
+       ut_params->op->xform->next->auth.key.data = hmac_sha1_key;
+       ut_params->op->xform->next->auth.digest_length = 
DIGEST_BYTE_LENGTH_SHA1;
+
+       ut_params->op->digest.data = ut_params->digest;
+       ut_params->op->digest.phys_addr = 
rte_pktmbuf_mtophys_offset(ut_params->ibuf,
+                       QUOTE_512_BYTES);
+       ut_params->op->digest.length = DIGEST_BYTE_LENGTH_SHA1;
+
+       ut_params->op->iv.data = (uint8_t *)rte_pktmbuf_prepend(ut_params->ibuf,
+                       CIPHER_IV_LENGTH_AES_CBC);
+       ut_params->op->iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
+       ut_params->op->iv.length = CIPHER_IV_LENGTH_AES_CBC;
+
+       rte_memcpy(ut_params->op->iv.data, aes_cbc_iv, 
CIPHER_IV_LENGTH_AES_CBC);
+
+       ut_params->op->data.to_cipher.offset = CIPHER_IV_LENGTH_AES_CBC;
+       ut_params->op->data.to_cipher.length = QUOTE_512_BYTES;
+       ut_params->op->data.to_hash.offset = CIPHER_IV_LENGTH_AES_CBC;
+       ut_params->op->data.to_hash.length = QUOTE_512_BYTES;
+
+       rte_pktmbuf_attach_crypto_op(ut_params->ibuf, ut_params->op);
+
+       /* Process crypto operation */
+       ut_params->obuf = process_crypto_request(ts_params->valid_devs[0],
+                       ut_params->ibuf);
+       TEST_ASSERT_NOT_NULL(ut_params->obuf, "failed to retrieve obuf");
+
+       /* Validate obuf */
+       TEST_ASSERT_BUFFERS_ARE_EQUAL(
+                       rte_pktmbuf_mtod(ut_params->obuf, uint8_t *) +
+                       CIPHER_IV_LENGTH_AES_CBC,
+                       catch_22_quote_2_512_bytes_AES_CBC_ciphertext,
+                       QUOTE_512_BYTES,
+                       "Ciphertext data not as expected");
+
+       TEST_ASSERT_BUFFERS_ARE_EQUAL(
+                       rte_pktmbuf_mtod(ut_params->obuf, uint8_t *) +
+                       CIPHER_IV_LENGTH_AES_CBC + QUOTE_512_BYTES,
+                       catch_22_quote_2_512_bytes_AES_CBC_HMAC_SHA1_digest,
+                       gbl_cryptodev_type == RTE_CRYPTODEV_AESNI_MB_PMD ?
+                                       TRUNCATED_DIGEST_BYTE_LENGTH_SHA1 :
+                                       DIGEST_BYTE_LENGTH_SHA1,
+                       "Generated digest data not as expected");
+
+       free_testsuite_mbufs();
+       return TEST_SUCCESS;
+}
+
 static int
 test_AES_CBC_HMAC_SHA1_decrypt_digest_verify(void)
 {
@@ -542,22 +648,27 @@ test_AES_CBC_HMAC_SHA1_decrypt_digest_verify(void)
                        DIGEST_BYTE_LENGTH_SHA1);

        /* Setup Cipher Parameters */
-       ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-       ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
-       ut_params->cipher_params.key.data = aes_cbc_key;
-       ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+       ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+       ut_params->cipher_xform.next = NULL;
+
+       ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+       ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
+       ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+       ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;

        /* Setup HMAC Parameters */
-       ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
-       ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
-       ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA1;
-       ut_params->hash_params.auth_key.data = hmac_sha1_key;
-       ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA1;
+       ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+       ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+       ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
+       ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
+       ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA1;
+       ut_params->auth_xform.auth.key.data = hmac_sha1_key;
+       ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA1;

        /* Create Crypto session*/
        ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-                       &ut_params->cipher_params, &ut_params->hash_params,
-                       RTE_CRYPTO_SYM_OPCHAIN_HASH_CIPHER);
+                       &ut_params->auth_xform);
        TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");

        /* Generate Crypto op data structure */
@@ -641,22 +752,27 @@ test_AES_CBC_HMAC_SHA256_encrypt_digest(void)
        TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");

        /* Setup Cipher Parameters */
-       ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-       ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
-       ut_params->cipher_params.key.data = aes_cbc_key;
-       ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+       ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+       ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+       ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+       ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
+       ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+       ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;

        /* Setup HMAC Parameters */
-       ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
-       ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;
-       ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA256;
-       ut_params->hash_params.auth_key.data = hmac_sha256_key;
-       ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA256;
+       ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+       ut_params->auth_xform.next = NULL;
+
+       ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
+       ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;
+       ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA256;
+       ut_params->auth_xform.auth.key.data = hmac_sha256_key;
+       ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA256;

        /* Create Crypto session*/
        ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-                       &ut_params->cipher_params, &ut_params->hash_params,
-                       RTE_CRYPTO_SYM_OPCHAIN_CIPHER_HASH);
+                       &ut_params->cipher_xform);
        TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");

        /* Generate Crypto op data structure */
@@ -731,22 +847,27 @@ test_AES_CBC_HMAC_SHA256_decrypt_digest_verify(void)
                        DIGEST_BYTE_LENGTH_SHA256);

        /* Setup Cipher Parameters */
-       ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-       ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
-       ut_params->cipher_params.key.data = aes_cbc_key;
-       ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+       ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+       ut_params->cipher_xform.next = NULL;
+
+       ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+       ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
+       ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+       ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;

        /* Setup HMAC Parameters */
-       ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
-       ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;
-       ut_params->hash_params.auth_key.data = hmac_sha256_key;
-       ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA256;
-       ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA256;
+       ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+       ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+       ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
+       ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;
+       ut_params->auth_xform.auth.key.data = hmac_sha256_key;
+       ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA256;
+       ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA256;

        /* Create Crypto session*/
        ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-                       &ut_params->cipher_params, &ut_params->hash_params,
-                       RTE_CRYPTO_SYM_OPCHAIN_HASH_CIPHER);
+                       &ut_params->auth_xform);
        TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");

        /* Generate Crypto op data structure */
@@ -837,22 +958,27 @@ test_AES_CBC_HMAC_SHA512_encrypt_digest(void)
        TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");

        /* Setup Cipher Parameters */
-       ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-       ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
-       ut_params->cipher_params.key.data = aes_cbc_key;
-       ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+       ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+       ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+       ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+       ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
+       ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+       ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;

        /* Setup HMAC Parameters */
-       ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
-       ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA512_HMAC;
-       ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA512;
-       ut_params->hash_params.auth_key.data = hmac_sha512_key;
-       ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA512;
+       ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+       ut_params->auth_xform.next = NULL;
+
+       ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
+       ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA512_HMAC;
+       ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA512;
+       ut_params->auth_xform.auth.key.data = hmac_sha512_key;
+       ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA512;

        /* Create Crypto session*/
        ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-                       &ut_params->cipher_params, &ut_params->hash_params,
-                       RTE_CRYPTO_SYM_OPCHAIN_CIPHER_HASH);
+                       &ut_params->cipher_xform);

        TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");

@@ -931,8 +1057,7 @@ test_AES_CBC_HMAC_SHA512_decrypt_digest_verify(void)

        /* Create Crypto session*/
        ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-                       &ut_params->cipher_params, &ut_params->hash_params,
-                       RTE_CRYPTO_SYM_OPCHAIN_HASH_CIPHER);
+                       &ut_params->auth_xform);
        TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");

        return test_AES_CBC_HMAC_SHA512_decrypt_perform(ut_params->sess,
@@ -944,17 +1069,23 @@ 
test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(struct crypto_unittest_pa
 {

        /* Setup Cipher Parameters */
-       ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-       ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
-       ut_params->cipher_params.key.data = aes_cbc_key;
-       ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+       ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+       ut_params->cipher_xform.next = NULL;
+
+       ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+       ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
+       ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+       ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;

        /* Setup HMAC Parameters */
-       ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
-       ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA512_HMAC;
-       ut_params->hash_params.auth_key.data = hmac_sha512_key;
-       ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA512;
-       ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA512;
+       ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+       ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+       ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
+       ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA512_HMAC;
+       ut_params->auth_xform.auth.key.data = hmac_sha512_key;
+       ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA512;
+       ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA512;
        return TEST_SUCCESS;
 }

@@ -1047,6 +1178,11 @@ static struct unit_test_suite cryptodev_testsuite  = {
                TEST_CASE_ST(ut_setup, ut_teardown, 
test_AES_CBC_HMAC_SHA512_encrypt_digest),
                TEST_CASE_ST(ut_setup, ut_teardown, 
test_AES_CBC_HMAC_SHA512_decrypt_digest_verify),

+               TEST_CASE_ST(ut_setup, ut_teardown, 
test_AES_CBC_HMAC_AES_XCBC_encrypt_digest),
+               TEST_CASE_ST(ut_setup, ut_teardown, 
test_AES_CBC_HMAC_AES_XCBC_decrypt_digest_verify),
+
+               TEST_CASE_ST(ut_setup, ut_teardown, 
test_AES_CBC_HMAC_SHA1_encrypt_digest_sessionless),
+
                TEST_CASES_END() /**< NULL terminate unit test array */
        }
 };
diff --git a/drivers/crypto/aesni_mb/aesni_mb_ops.h 
b/drivers/crypto/aesni_mb/aesni_mb_ops.h
index ab96990..1188278 100644
--- a/drivers/crypto/aesni_mb/aesni_mb_ops.h
+++ b/drivers/crypto/aesni_mb/aesni_mb_ops.h
@@ -59,7 +59,7 @@ typedef void (*aes_keyexp_128_t)(void *key, void 
*enc_exp_keys, void *dec_exp_ke
 typedef void (*aes_keyexp_192_t)(void *key, void *enc_exp_keys, void 
*dec_exp_keys);
 typedef void (*aes_keyexp_256_t)(void *key, void *enc_exp_keys, void 
*dec_exp_keys);

-typedef void (*aes_xcbc_expand_key_t)(void *key, void *k1_exp, void *k2, void 
*k3);
+typedef void (*aes_xcbc_expand_key_t)(void *key, void *exp_k1, void *k2, void 
*k3);

 typedef void (*aesni_gcm_t)(gcm_data *my_ctx_data, u8 *out, const u8 *in,
                u64 plaintext_len, u8 *iv, const u8 *aad, u64 aad_len,
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c 
b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 65a3731..506754e 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -104,31 +104,101 @@ calculate_auth_precomputes(hash_one_block_t 
one_block_hash,
        memset(opad_buf, 0, blocksize);
 }

-int
-aesni_mb_set_session_parameters(const struct aesni_mb_ops *mb_ops,
+static int
+aesni_mb_get_chain_order(const struct rte_crypto_xform *xform)
+{
+       /* multi-buffer only supports HASH_CIPHER or CIPHER_HASH chained
+        * operations, all other options are invalid, so we must have exactly
+        * 2 xform structs chained together */
+       if (xform->next == NULL || xform->next->next != NULL)
+               return -1;
+
+       if (xform->type == RTE_CRYPTO_XFORM_AUTH &&
+                       xform->next->type == RTE_CRYPTO_XFORM_CIPHER)
+               return HASH_CIPHER;
+
+       if (xform->type == RTE_CRYPTO_XFORM_CIPHER &&
+                               xform->next->type == RTE_CRYPTO_XFORM_AUTH)
+               return CIPHER_HASH;
+
+       return -1;
+}
+
+static int
+aesni_mb_set_session_auth_parameters(const struct aesni_mb_ops *mb_ops,
                struct aesni_mb_session *sess,
-               struct rte_crypto_cipher_params *cipher_params,
-               struct rte_crypto_hash_params *auth_params,
-               enum rte_crypto_operation_chain op_chain)
+               const struct rte_crypto_xform *xform)
 {
-       aes_keyexp_t aes_keyexp_fn;
        hash_one_block_t hash_oneblock_fn;

-       /* Select Crypto operation - hash then cipher / cipher then hash */
-       switch (op_chain) {
-       case RTE_CRYPTO_SYM_OPCHAIN_HASH_CIPHER:
-               sess->chain_order = HASH_CIPHER;
+       if (xform->type != RTE_CRYPTO_XFORM_AUTH) {
+               MB_LOG_ERR("Crypto xform struct not of type auth");
+               return -1;
+       }
+
+       /* Set Authentication Parameters */
+       if (xform->auth.algo == RTE_CRYPTO_SYM_HASH_AES_XCBC_MAC) {
+               sess->auth.algo = AES_XCBC;
+               (*mb_ops->aux.keyexp.aes_xcbc)(xform->auth.key.data,
+                               sess->auth.xcbc.k1_expanded,
+                               sess->auth.xcbc.k2, sess->auth.xcbc.k3);
+               return 0;
+       }
+
+       switch (xform->auth.algo) {
+       case RTE_CRYPTO_SYM_HASH_MD5_HMAC:
+               sess->auth.algo = MD5;
+               hash_oneblock_fn = mb_ops->aux.one_block.md5;
                break;
-       case RTE_CRYPTO_SYM_OPCHAIN_CIPHER_HASH:
-               sess->chain_order = CIPHER_HASH;
+       case RTE_CRYPTO_SYM_HASH_SHA1_HMAC:
+               sess->auth.algo = SHA1;
+               hash_oneblock_fn = mb_ops->aux.one_block.sha1;
+               break;
+       case RTE_CRYPTO_SYM_HASH_SHA224_HMAC:
+               sess->auth.algo = SHA_224;
+               hash_oneblock_fn = mb_ops->aux.one_block.sha224;
+               break;
+       case RTE_CRYPTO_SYM_HASH_SHA256_HMAC:
+               sess->auth.algo = SHA_256;
+               hash_oneblock_fn = mb_ops->aux.one_block.sha256;
+               break;
+       case RTE_CRYPTO_SYM_HASH_SHA384_HMAC:
+               sess->auth.algo = SHA_384;
+               hash_oneblock_fn = mb_ops->aux.one_block.sha384;
+               break;
+       case RTE_CRYPTO_SYM_HASH_SHA512_HMAC:
+               sess->auth.algo = SHA_512;
+               hash_oneblock_fn = mb_ops->aux.one_block.sha512;
                break;
        default:
-               printf("unsupported operation chain order parameter");
+               MB_LOG_ERR("Unsupported authentication algorithm selection");
+               return -1;
+       }
+
+       /* Calculate Authentication precomputes */
+       calculate_auth_precomputes(hash_oneblock_fn,
+                       sess->auth.pads.inner, sess->auth.pads.outer,
+                       xform->auth.key.data,
+                       xform->auth.key.length,
+                       get_auth_algo_blocksize(sess->auth.algo));
+
+       return 0;
+}
+
+static int
+aesni_mb_set_session_cipher_parameters(const struct aesni_mb_ops *mb_ops,
+               struct aesni_mb_session *sess,
+               const struct rte_crypto_xform *xform)
+{
+       aes_keyexp_t aes_keyexp_fn;
+
+       if (xform->type != RTE_CRYPTO_XFORM_CIPHER) {
+               MB_LOG_ERR("Crypto xform struct not of type cipher");
                return -1;
        }

        /* Select cipher direction */
-       switch (cipher_params->op) {
+       switch (xform->cipher.op) {
        case RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT:
                sess->cipher.direction = ENCRYPT;
                break;
@@ -136,22 +206,22 @@ aesni_mb_set_session_parameters(const struct aesni_mb_ops 
*mb_ops,
                sess->cipher.direction = DECRYPT;
                break;
        default:
-               printf("unsupported cipher operation parameter");
+               MB_LOG_ERR("Unsupported cipher operation parameter");
                return -1;
        }

        /* Select cipher mode */
-       switch (cipher_params->algo) {
+       switch (xform->cipher.algo) {
        case RTE_CRYPTO_SYM_CIPHER_AES_CBC:
                sess->cipher.mode = CBC;
                break;
        default:
-               printf("unsupported cipher mode parameter");
+               MB_LOG_ERR("Unsupported cipher mode parameter");
                return -1;
        }

        /* Check key length and choose key expansion function */
-       switch (cipher_params->key.length) {
+       switch (xform->cipher.key.length) {
        case AES_128_BYTES:
                sess->cipher.key_length_in_bytes = AES_128_BYTES;
                aes_keyexp_fn = mb_ops->aux.keyexp.aes128;
@@ -165,53 +235,53 @@ aesni_mb_set_session_parameters(const struct aesni_mb_ops 
*mb_ops,
                aes_keyexp_fn = mb_ops->aux.keyexp.aes256;
                break;
        default:
-               printf("unsupported cipher key length");
+               MB_LOG_ERR("Unsupported cipher key length");
                return -1;
        }

        /* Expanded cipher keys */
-       (*aes_keyexp_fn)(cipher_params->key.data,
+       (*aes_keyexp_fn)(xform->cipher.key.data,
                        sess->cipher.expanded_aes_keys.encode,
                        sess->cipher.expanded_aes_keys.decode);

-       /* Set Authentication Parameters */
-       switch (auth_params->algo) {
-       case RTE_CRYPTO_SYM_HASH_MD5_HMAC:
-               sess->auth.algo = MD5;
-               hash_oneblock_fn = mb_ops->aux.one_block.md5;
-               break;
-       case RTE_CRYPTO_SYM_HASH_SHA1_HMAC:
-               sess->auth.algo = SHA1;
-               hash_oneblock_fn = mb_ops->aux.one_block.sha1;
-               break;
-       case RTE_CRYPTO_SYM_HASH_SHA224_HMAC:
-               sess->auth.algo = SHA_224;
-               hash_oneblock_fn = mb_ops->aux.one_block.sha224;
-               break;
-       case RTE_CRYPTO_SYM_HASH_SHA256_HMAC:
-               sess->auth.algo = SHA_256;
-               hash_oneblock_fn = mb_ops->aux.one_block.sha256;
-               break;
-       case RTE_CRYPTO_SYM_HASH_SHA384_HMAC:
-               sess->auth.algo = SHA_384;
-               hash_oneblock_fn = mb_ops->aux.one_block.sha384;
+       return 0;
+}
+
+
+int
+aesni_mb_set_session_parameters(const struct aesni_mb_ops *mb_ops,
+               struct aesni_mb_session *sess,
+               const struct rte_crypto_xform *xform)
+{
+       const struct rte_crypto_xform *auth_xform = NULL;
+       const struct rte_crypto_xform *cipher_xform = NULL;
+
+       /* Select Crypto operation - hash then cipher / cipher then hash */
+       switch (aesni_mb_get_chain_order(xform)) {
+       case HASH_CIPHER:
+               sess->chain_order = HASH_CIPHER;
+               auth_xform = xform;
+               cipher_xform = xform->next;
                break;
-       case RTE_CRYPTO_SYM_HASH_SHA512_HMAC:
-               sess->auth.algo = SHA_512;
-               hash_oneblock_fn = mb_ops->aux.one_block.sha512;
+       case CIPHER_HASH:
+               sess->chain_order = CIPHER_HASH;
+               auth_xform = xform->next;
+               cipher_xform = xform;
                break;
        default:
-               printf("unsupported authentication algorithm selection");
+               MB_LOG_ERR("Unsupported operation chain order parameter");
                return -1;
        }

-       /* Calculate Authentication precomputes */
-       calculate_auth_precomputes(hash_oneblock_fn,
-                       sess->auth.pads.inner, sess->auth.pads.outer,
-                       auth_params->auth_key.data,
-                       auth_params->auth_key.length,
-                       get_auth_algo_blocksize(sess->auth.algo));
+       if (aesni_mb_set_session_auth_parameters(mb_ops, sess, auth_xform)) {
+               MB_LOG_ERR("Invalid/unsupported authentication parameters");
+               return -1;
+       }

+       if (aesni_mb_set_session_cipher_parameters(mb_ops, sess, cipher_xform)) 
{
+               MB_LOG_ERR("Invalid/unsupported cipher parameters");
+               return -1;
+       }
        return 0;
 }

@@ -239,9 +309,7 @@ process_crypto_op(struct aesni_mb_qp *qp, JOB_AES_HMAC 
*job, struct rte_mbuf *m)
                        return NULL;

                if (unlikely(aesni_mb_set_session_parameters(qp->mb_ops,
-                               sess, &c_op->op_params.cipher,
-                               &c_op->op_params.hash,
-                               c_op->op_params.opchain) != 0))
+                               sess, c_op->xform) != 0))
                        return NULL;
        } else {
                sess = (struct aesni_mb_session *)c_op->session;
@@ -250,7 +318,6 @@ process_crypto_op(struct aesni_mb_qp *qp, JOB_AES_HMAC 
*job, struct rte_mbuf *m)
        /* Set crypto operation */
        job->chain_order = sess->chain_order;

-
        /* Set cipher parameters */
        job->cipher_direction = sess->cipher.direction;
        job->cipher_mode = sess->cipher.mode;
@@ -262,9 +329,14 @@ process_crypto_op(struct aesni_mb_qp *qp, JOB_AES_HMAC 
*job, struct rte_mbuf *m)

        /* Set authentication parameters */
        job->hash_alg = sess->auth.algo;
-       job->hashed_auth_key_xor_ipad = sess->auth.pads.inner;
-       job->hashed_auth_key_xor_opad = sess->auth.pads.outer;
-
+       if (job->hash_alg == AES_XCBC) {
+               job->_k1_expanded = sess->auth.xcbc.k1_expanded;
+               job->_k2 = sess->auth.xcbc.k2;
+               job->_k3 = sess->auth.xcbc.k3;
+       } else {
+               job->hashed_auth_key_xor_ipad = sess->auth.pads.inner;
+               job->hashed_auth_key_xor_opad = sess->auth.pads.outer;
+       }

        /* Mutable crypto operation parameters */

diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c 
b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
index fb57e7b..d9cdd5b 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -286,9 +286,7 @@ aesni_mb_pmd_session_mempool_create(struct rte_cryptodev 
*dev,

 static struct rte_cryptodev_session *
 aesni_mb_pmd_create_session(struct rte_cryptodev *dev,
-               struct rte_crypto_cipher_params *cipher_setup_data,
-               struct rte_crypto_hash_params *hash_setup_data,
-               enum rte_crypto_operation_chain op_chain)
+               struct rte_crypto_xform *xform)
 {
        struct aesni_mb_private *internals = dev->data->dev_private;
        struct aesni_mb_session *sess  =
@@ -299,9 +297,9 @@ aesni_mb_pmd_create_session(struct rte_cryptodev *dev,
                return NULL;
        }

-       if (aesni_mb_set_session_parameters(
-                       &job_ops[internals->vector_mode], sess,
-                       cipher_setup_data, hash_setup_data, op_chain) != 0) {
+       if (aesni_mb_set_session_parameters(&job_ops[internals->vector_mode],
+                       sess, xform) != 0) {
+               MB_LOG_ERR("failed configure session parameters");
                aesni_mb_free_session(internals->sess_mp, sess);
        }

diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h 
b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
index c5c4a86..abfec16 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
@@ -178,13 +178,21 @@ struct aesni_mb_session {

        struct {
                JOB_HASH_ALG algo;      /** Authentication Algorithm */
-
-               struct {
-                       uint8_t inner[128] __rte_align(16);     /**< inner pad 
*/
-                       uint8_t outer[128] __rte_align(16);     /**< outer pad 
*/
-               } pads;
-               /** HMAC Authentication pads - allocating space for the maximum
-                * pad size supported which is 128 bytes for SHA512 */
+               union {
+                       struct {
+                               uint8_t inner[128] __rte_align(16);     /**< 
inner pad */
+                               uint8_t outer[128] __rte_align(16);     /**< 
outer pad */
+                       } pads;
+                       /** HMAC Authentication pads - allocating space for the 
maximum
+                        * pad size supported which is 128 bytes for SHA512 */
+
+                       struct {
+                           uint32_t k1_expanded[44] __rte_align(16);   /* k1 
(expanded key). */
+                           uint8_t k2[16] __rte_align(16);             /* k2. 
*/
+                           uint8_t k3[16] __rte_align(16);             /* k3. 
*/
+                       } xcbc;
+                       /** Expanded XCBC authentication keys */
+               };

                uint8_t digest[64] __rte_align(16);
        } auth; /**< Authentication Parameters */
@@ -212,10 +220,10 @@ aesni_mb_free_session(struct rte_mempool *mempool,
 extern int
 aesni_mb_set_session_parameters(const struct aesni_mb_ops *mb_ops,
                struct aesni_mb_session *sess,
-               struct rte_crypto_cipher_params *cparams,
-               struct rte_crypto_hash_params *aparams,
-               enum rte_crypto_operation_chain op_chain);
+               const struct rte_crypto_xform *xform);
+

+/** device specific operations function pointer structure */
 extern struct rte_cryptodev_ops *rte_aesni_mb_pmd_ops;


diff --git a/lib/librte_cryptodev/rte_crypto.h 
b/lib/librte_cryptodev/rte_crypto.h
index b776609..2160003 100644
--- a/lib/librte_cryptodev/rte_crypto.h
+++ b/lib/librte_cryptodev/rte_crypto.h
@@ -121,8 +121,8 @@ enum rte_crypto_cipher_algorithm {
        RTE_CRYPTO_SYM_CIPHER_AES_F8,
        /**< AES algorithm in F8 mode */
        RTE_CRYPTO_SYM_CIPHER_AES_GCM,
-       /**< AES algorithm in CGM mode. When this cipher algorithm is used the
-        * *RTE_CRYPTO_SYM_CIPHER_AES_GCM* element of the
+       /**< AES algorithm in GCM mode. When this cipher algorithm is used the
+        * *RTE_CRYPTO_SYM_HASH_AES_GCM* element of the
         * *rte_crypto_hash_algorithm* enum MUST be used to set up the related
         * *rte_crypto_hash_setup_data* structure in the session context or in
         * the op_params of the crypto operation structure in the case of a
@@ -164,7 +164,7 @@ struct rte_crypto_key {
  * This structure contains data relating to Cipher (Encryption and Decryption)
  *  use to create a session.
  */
-struct rte_crypto_cipher_params {
+struct rte_crypto_cipher_xform {
        enum rte_crypto_cipher_operation op;
        /**< This parameter determines if the cipher operation is an encrypt or
         * a decrypt operation. For the RC4 algorithm and the F8/CTR modes,
@@ -203,8 +203,8 @@ struct rte_crypto_cipher_params {
         **/
 };

-/** Symmetric Hash / Authentication Algorithms */
-enum rte_crypto_hash_algorithm {
+/** Symmetric Authentication / Hash Algorithms */
+enum rte_crypto_auth_algorithm {
        RTE_CRYPTO_SYM_HASH_NONE = 0,
        /**< No hash algorithm. */

@@ -276,27 +276,24 @@ enum rte_crypto_hash_algorithm {
        /**< ZUC algorithm in EIA3 mode */
 };

-/** Symmetric Hash Operations */
-enum rte_crypto_hash_operation {
+/** Symmetric Authentication / Hash Operations */
+enum rte_crypto_auth_operation {
        RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY,   /**< Verify digest */
        RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE  /**< Generate digest */
 };

 /**
- * Hash Setup Data.
+ * Authentication / Hash transform data.
  *
- * This structure contains data relating to a hash session. The fields 
hash_algorithm, hash_mode and digest_result_len are common to all
- *      three hash modes and MUST be set for each mode.
- *
- *****************************************************************************/
-struct rte_crypto_hash_params {
-       enum rte_crypto_hash_operation op;
-       /* hash operation type */
-       enum rte_crypto_hash_algorithm algo;
-       /* hashing algorithm selection */
-
-       struct rte_crypto_key auth_key;
-       /**< Authentication key data.
+ * This structure contains data relating to an authentication/hash crypto
+ * transforms. The fields op, algo and digest_length are common to all
+ * authentication transforms and MUST be set.
+ */
+struct rte_crypto_auth_xform {
+       enum rte_crypto_auth_operation op;      /**< Authentication operation 
type */
+       enum rte_crypto_auth_algorithm algo;    /**< Authentication algorithm 
selection */
+
+       struct rte_crypto_key key;              /**< Authentication key data.
         * The authentication key length MUST be less than or equal to the
         * block size of the algorithm. It is the callers responsibility to
         * ensure that the key length is compliant with the standard being used
@@ -346,9 +343,36 @@ struct rte_crypto_hash_params {
 };

 /**
+ * Defines the crypto transforms available
+ */
+enum rte_crypto_xform_type {
+       RTE_CRYPTO_XFORM_NOT_SPECIFIED = 0,
+       RTE_CRYPTO_XFORM_AUTH,
+       RTE_CRYPTO_XFORM_CIPHER
+};
+
+/**
+ * Crypto transform structure.
+ *
+ * This is used to specify the crypto transforms required, multiple transforms
+ * can be chained together to specify a chain transforms such as authentication
+ * then cipher, or cipher then authentication. Each transform structure can
+ * hold a single transform, the type field is used to specify which transform
+ * is contained within the union */
+struct rte_crypto_xform {
+       struct rte_crypto_xform *next; /**< next xform in chain */
+
+       enum rte_crypto_xform_type type; /**< xform type */
+       union {
+               struct rte_crypto_auth_xform auth;      /**< Authentication / 
hash xform */
+               struct rte_crypto_cipher_xform cipher;  /**< Cipher xform */
+       };
+};
+
+/**
  * Crypto operation session type. This is used to specify whether a crypto
  * operation has session structure attached for immutable parameters or if all
- * operation information is include in the operation data structure op_params.
+ * operation information is included in the operation data structure.
  */
 enum rte_crypto_op_sess_type {
        RTE_CRYPTO_OP_WITH_SESSION,     /**< Session based crypto operation */
@@ -370,11 +394,7 @@ struct rte_crypto_op_data {
        union {
                struct rte_cryptodev_session *session;
                /**< Handle for the initialised session context */
-               struct {
-                       struct rte_crypto_cipher_params cipher;
-                       struct rte_crypto_hash_params hash;
-                       enum rte_crypto_operation_chain opchain;
-               } op_params;
+               struct rte_crypto_xform *xform;
                /**< Session-less API crypto operation parameters */
        };

@@ -570,6 +590,20 @@ struct rte_crypto_op_data {
        struct rte_mempool *pool;       /**< mempool used to allocate crypto op 
*/
 };

+
+/**
+ * Crypto Operation Pool Private Data Structure
+ */
+struct crypto_op_pool_private {
+       unsigned max_nb_xforms;
+};
+
+
+extern struct rte_mempool *
+rte_crypto_op_pool_create(const char *name, unsigned nb_ops,
+               unsigned cache_size, unsigned nb_xforms, int socket_id);
+
+
 /**
  * Reset the fields of a packet mbuf to their default values.
  *
@@ -579,9 +613,8 @@ struct rte_crypto_op_data {
  *   The packet mbuf to be resetted.
  */
 static inline void
-rte_crypto_op_reset(struct rte_crypto_op_data *op)
+__rte_crypto_op_reset(struct rte_crypto_op_data *op)
 {
-
        op->type = RTE_CRYPTO_OP_SESSIONLESS;
 }

@@ -597,13 +630,10 @@ __rte_crypto_op_raw_alloc(struct rte_mempool *mp)
 }

 /**
- * Create an crypto operation structure which is used to define the crypto
- * operation processing which is to be done on a packet.
+ * Allocate a crypto operation structure from an crypto pool which is used 
+ * to define the crypto operation processing which is to be done on a packet.
  *
- * @param      dev_id          Device identifier
- * @param      m_src           Source mbuf of data for processing.
- * @param      m_dst           Destination mbuf for processed data. Can be NULL
- *                             if crypto operation is done in place.
+ * @param      mp              crypto operation pool
  */
 static inline struct rte_crypto_op_data *
 rte_crypto_op_alloc(struct rte_mempool *mp)
@@ -611,7 +641,41 @@ rte_crypto_op_alloc(struct rte_mempool *mp)
        struct rte_crypto_op_data *op;

        if ((op = __rte_crypto_op_raw_alloc(mp)) != NULL)
-               rte_crypto_op_reset(op);
+               __rte_crypto_op_reset(op);
+       return op;
+}
+
+/**
+ * Allocate a sessionless crypto operation structure from an crypto pool which 
is used 
+ * to define the crypto operation processing which is to be done on a packet. 
The number of
+ * xforms supported is calculated from the mempools private data is used to 
check whether
+ * enough extra data has been allocated for each xform requested after the 
operation structure
+ *
+ * @param      mp                      crypto operation pool
+ * @param      nb_xforms       number of crypto transforms to be used in 
operation
+ */
+static inline struct rte_crypto_op_data *
+rte_crypto_op_alloc_sessionless(struct rte_mempool *mp, unsigned nb_xforms)
+{
+       struct rte_crypto_op_data *op = NULL;
+       struct rte_crypto_xform *xform = NULL;
+       struct crypto_op_pool_private *priv_data =
+                                       (struct crypto_op_pool_private *)
+                                       rte_mempool_get_priv(mp);
+
+       if (nb_xforms > priv_data->max_nb_xforms && nb_xforms > 0)
+               return op;
+
+       if ((op = __rte_crypto_op_raw_alloc(mp)) != NULL) {
+               __rte_crypto_op_reset(op);
+
+               xform = op->xform = (struct rte_crypto_xform *)(op + 1);
+
+               do {
+                       xform->type = RTE_CRYPTO_XFORM_NOT_SPECIFIED;
+                       xform = xform->next = --nb_xforms > 0 ? xform + 1 : 
NULL;
+               } while (xform);
+       }
        return op;
 }

@@ -629,10 +693,9 @@ rte_crypto_op_free(struct rte_crypto_op_data *op)
        }
 }

-extern struct rte_mempool *
-rte_crypto_op_pool_create(const char *name, unsigned n, unsigned cache_size,
-               int socket_id);
-
+/**
+ * Attach a session to a crypto operation
+ */
 static inline void
 rte_crypto_op_attach_session(struct rte_crypto_op_data *op,
                struct rte_cryptodev_session *sess)
diff --git a/lib/librte_cryptodev/rte_cryptodev.c 
b/lib/librte_cryptodev/rte_cryptodev.c
index a1797ce..7f2e5d1 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -101,13 +101,13 @@
        } \
 } while (0)

-struct rte_cryptodev rte_crypto_devices[RTE_MAX_CRYPTODEVS];
+struct rte_cryptodev rte_crypto_devices[RTE_CRYPTO_MAX_DEVS];

 static struct rte_cryptodev_global cryptodev_globals = {
                .devs                   = &rte_crypto_devices[0],
                .data                   = NULL,
                .nb_devs                = 0,
-               .max_devs               = RTE_MAX_CRYPTODEVS
+               .max_devs               = RTE_CRYPTO_MAX_DEVS
 };

 struct rte_cryptodev_global *rte_cryptodev_globals = &cryptodev_globals;
@@ -164,11 +164,11 @@ rte_cryptodev_find_free_device_index(void)
 {
        uint8_t dev_id;

-       for (dev_id = 0; dev_id < RTE_MAX_CRYPTODEVS; dev_id++) {
+       for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) {
                if (rte_crypto_devices[dev_id].attached == 
RTE_CRYPTODEV_DETACHED)
                        return dev_id;
        }
-       return RTE_MAX_CRYPTODEVS;
+       return RTE_CRYPTO_MAX_DEVS;
 }

 struct rte_cryptodev *
@@ -178,7 +178,7 @@ rte_cryptodev_pmd_allocate(const char *name, enum pmd_type 
type, int socket_id)
        struct rte_cryptodev *cryptodev;

        dev_id = rte_cryptodev_find_free_device_index();
-       if (dev_id == RTE_MAX_CRYPTODEVS) {
+       if (dev_id == RTE_CRYPTO_MAX_DEVS) {
                CDEV_LOG_ERR("Reached maximum number of crypto devices");
                return NULL;
        }
@@ -868,9 +868,7 @@ rte_cryptodev_pmd_callback_process(struct rte_cryptodev 
*dev,

 struct rte_cryptodev_session *
 rte_cryptodev_session_create(uint8_t dev_id,
-               struct rte_crypto_cipher_params *cipher_setup_data,
-               struct rte_crypto_hash_params *hash_setup_data,
-               enum rte_crypto_operation_chain op_chain)
+               struct rte_crypto_xform *xform)
 {
        struct rte_cryptodev *dev;

@@ -879,10 +877,10 @@ rte_cryptodev_session_create(uint8_t dev_id,
                return NULL;
        }

-        dev = &rte_crypto_devices[dev_id];
+       dev = &rte_crypto_devices[dev_id];

-        return dev->dev_ops->session_create(dev, cipher_setup_data,
-                        hash_setup_data, op_chain);
+       FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_create, NULL);
+       return dev->dev_ops->session_create(dev, xform);
 }

 void
@@ -896,9 +894,10 @@ rte_cryptodev_session_free(uint8_t dev_id,
                return;
        }

-        dev = &rte_crypto_devices[dev_id];
+       dev = &rte_crypto_devices[dev_id];

-        dev->dev_ops->session_destroy(dev, session);
+       FUNC_PTR_OR_RET(*dev->dev_ops->session_destroy);
+       dev->dev_ops->session_destroy(dev, session);
 }


@@ -922,15 +921,24 @@ rte_crypto_op_pool_init(__rte_unused struct rte_mempool 
*mp,
 }

 struct rte_mempool *
-rte_crypto_op_pool_create(const char *name, unsigned n, unsigned cache_size,
-               int socket_id)
+rte_crypto_op_pool_create(const char *name, unsigned size,
+               unsigned cache_size, unsigned nb_xforms, int socket_id)
 {
+       struct crypto_op_pool_private *priv_data = NULL;
+
+       unsigned elt_size = sizeof(struct rte_crypto_op_data) +
+                       (sizeof(struct rte_crypto_xform) * nb_xforms);
+
        /* lookup mempool in case already allocated */
        struct rte_mempool *mp = rte_mempool_lookup(name);
        if (mp != NULL) {
-               if (mp->elt_size != sizeof(struct rte_crypto_op_data) ||
+               priv_data = (struct crypto_op_pool_private *)
+                               rte_mempool_get_priv(mp);
+
+               if (priv_data->max_nb_xforms <  nb_xforms ||
+                               mp->elt_size != elt_size ||
                                mp->cache_size < cache_size ||
-                               mp->size < n) {
+                               mp->size < size) {
                        mp = NULL;
                        CDEV_LOG_ERR("%s mempool already exists with "
                                        "incompatible initialisation 
parameters",
@@ -941,11 +949,12 @@ rte_crypto_op_pool_create(const char *name, unsigned n, 
unsigned cache_size,
                return mp;
        }

-       mp = rte_mempool_create(name,   /* mempool name */
-                       n,                      /* number of elements*/
-                       sizeof(struct rte_crypto_op_data),/* element size*/
+       mp = rte_mempool_create(
+                       name,                           /* mempool name */
+                       size,                           /* number of elements*/
+                       elt_size,                       /* element size*/
                        cache_size,                     /* Cache size*/
-                       0,                              /* private data size */
+                       sizeof(struct crypto_op_pool_private),  /* private data 
size */
                        rte_crypto_op_pool_init,        /* pool initialisation 
constructor */
                        NULL,                           /* pool initialisation 
constructor argument */
                        rte_crypto_op_init,             /* obj constructor */
@@ -958,6 +967,9 @@ rte_crypto_op_pool_create(const char *name, unsigned n, 
unsigned cache_size,
                return NULL;
        }

+       priv_data = (struct crypto_op_pool_private *)rte_mempool_get_priv(mp);
+
+       priv_data->max_nb_xforms = nb_xforms;

        CDEV_LOG_DEBUG("%s mempool created!", name);
        return mp;
diff --git a/lib/librte_cryptodev/rte_cryptodev.h 
b/lib/librte_cryptodev/rte_cryptodev.h
index d7694ad..d2d34f2 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -501,31 +501,23 @@ rte_cryptodev_enqueue_burst(uint8_t dev_id, uint16_t 
qp_id,
  * parameters of symmetric cryptographic operation.
  * To perform the operation the rte_cryptodev_enqueue_burst function is
  * used.  Each mbuf should contain a reference to the session
- * pointer returned from this function.
- * Memory to contain the session information is allocated by the
- * implementation.
- * An upper limit on the number of session that many be created is
- * defined by a build configuration constant.
+ * pointer returned from this function contained within it's crypto_op if a
+ * session-based operation is being provisioned. Memory to contain the session
+ * information is allocated from within mempool managed by the cryptodev.
+ *
  * The rte_cryptodev_session_free must be called to free allocated
- * memory when the session information is no longer needed.
+ * memory when the session is no longer required.
  *
- * @param      dev_id                  The device identifier.
- * @param      cipher_setup_data       The parameters associated with the
- *                                     cipher operation. This may be NULL.
- * @param      hash_setup_data         The parameters associated with the hash
- *                                     operation. This may be NULL.
- * @param      op_chain                Specifies the crypto operation chaining,
- *                                     cipher and/or hash and the order in
- *                                     which they are performed.
+ * @param      dev_id          The device identifier.
+ * @param      xform           Crypto transform chain.
+
  *
  * @return
  *  Pointer to the created session or NULL
  */
 extern struct rte_cryptodev_session *
 rte_cryptodev_session_create(uint8_t dev_id,
-               struct rte_crypto_cipher_params *cipher_setup_data,
-               struct rte_crypto_hash_params *hash_setup_data,
-               enum rte_crypto_operation_chain op_chain);
+               struct rte_crypto_xform *xform);


 /**
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h 
b/lib/librte_cryptodev/rte_cryptodev_pmd.h
index e6fdd1c..aa2f6c4 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.h
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h
@@ -453,10 +453,8 @@ typedef int (*cryptodev_create_session_pool_t)(
 /**
  * Create a Crypto session on a device.
  *
- * @param      dev                     Crypto device pointer
- * @param      cipher_setup_data       Cipher operation parameters
- * @param      hash_setup_data         Hash operation parameters
- * @param      op_chain                Operation chaining
+ * @param      dev             Crypto device pointer
+ * @param      xform           Single or chain of crypto xforms
  *
  * @return
  *  - Returns cryptodev session structure on success.
@@ -464,9 +462,7 @@ typedef int (*cryptodev_create_session_pool_t)(
  * */
 typedef struct rte_cryptodev_session * (*cryptodev_create_session_t)(
                struct rte_cryptodev *dev,
-               struct rte_crypto_cipher_params *cipher_setup_data,
-               struct rte_crypto_hash_params *hash_setup_data,
-               enum rte_crypto_operation_chain op_chain);
+               struct rte_crypto_xform *xform);

 /**
  * Free Crypto session.
-- 
2.4.3

Reply via email to