This patch provides unit tests for set of cipher/hash combinations covering
currently implemented crypto PMD's and allowing to verify scatter gather
support.


Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyg...@intel.com>
Signed-off-by: Tomasz Kulasek <tomaszx.kula...@intel.com>
---
 app/test/test_cryptodev.c                  |  456 ++++++++++++++++++++++++++++
 app/test/test_cryptodev.h                  |  111 +++++++
 app/test/test_cryptodev_aes_test_vectors.h |   32 +-
 app/test/test_cryptodev_blockcipher.c      |  170 +++++++----
 app/test/test_cryptodev_blockcipher.h      |    1 +
 5 files changed, 710 insertions(+), 60 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 872f8b4..613dae9 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -1688,6 +1688,10 @@ struct crypto_unittest_params {
 
        TEST_ASSERT_NOT_NULL(sym_op->cipher.iv.data, "no room to prepend iv");
 
+       /* For OOP operation both buffers must have the same size */
+       if (ut_params->obuf)
+               rte_pktmbuf_prepend(ut_params->obuf, iv_pad_len);
+
        memset(sym_op->cipher.iv.data, 0, iv_pad_len);
        sym_op->cipher.iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
        sym_op->cipher.iv.length = iv_pad_len;
@@ -2509,6 +2513,84 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_sgl(const struct kasumi_test_data *tdata)
+{
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+       struct crypto_unittest_params *ut_params = &unittest_params;
+
+       int retval;
+
+       unsigned plaintext_pad_len;
+       unsigned plaintext_len;
+
+       uint8_t buffer[10000];
+       const uint8_t *ciphertext;
+
+       struct rte_cryptodev_info dev_info;
+
+       rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+       if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+               printf("Device doesn't support scatter-gather. "
+                               "Test Skipped.\n");
+               return 0;
+       }
+
+       /* Create KASUMI session */
+       retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+                                       RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+                                       RTE_CRYPTO_CIPHER_KASUMI_F8,
+                                       tdata->key.data, tdata->key.len);
+       if (retval < 0)
+               return retval;
+
+       plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+
+       /* Append data which is padded to a multiple */
+       /* of the algorithms block size */
+       plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+       ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+                       plaintext_pad_len, 10);
+
+       pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+       /* Create KASUMI operation */
+       retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+                                       tdata->iv.len,
+                                       tdata->plaintext.len,
+                                       tdata->validCipherOffsetLenInBits.len,
+                                       RTE_CRYPTO_CIPHER_KASUMI_F8);
+       if (retval < 0)
+               return retval;
+
+       ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+                                               ut_params->op);
+       TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+       ut_params->obuf = ut_params->op->sym->m_dst;
+
+       if (ut_params->obuf)
+               ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+                               plaintext_len, buffer);
+       else
+               ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+                               plaintext_len, buffer);
+
+       /* Validate obuf */
+       TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+               /* Validate obuf */
+               TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+                       ciphertext,
+                       tdata->ciphertext.data,
+                       tdata->validCipherLenInBits.len,
+                       "KASUMI Ciphertext data not as expected");
+               return 0;
+}
+
+
+static int
 test_kasumi_encryption_oop(const struct kasumi_test_data *tdata)
 {
        struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2577,6 +2659,81 @@ struct crypto_unittest_params {
 }
 
 static int
+test_kasumi_encryption_oop_sgl(const struct kasumi_test_data *tdata)
+{
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+       struct crypto_unittest_params *ut_params = &unittest_params;
+
+       int retval;
+       unsigned plaintext_pad_len;
+       unsigned plaintext_len;
+
+       const uint8_t *ciphertext;
+       uint8_t buffer[2048];
+
+       struct rte_cryptodev_info dev_info;
+
+       rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+       if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+               printf("Device doesn't support scatter-gather. "
+                               "Test Skipped.\n");
+               return 0;
+       }
+
+       /* Create KASUMI session */
+       retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+                                       RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+                                       RTE_CRYPTO_CIPHER_KASUMI_F8,
+                                       tdata->key.data, tdata->key.len);
+       if (retval < 0)
+               return retval;
+
+       plaintext_len = ceil_byte_length(tdata->plaintext.len);
+       /* Append data which is padded to a multiple */
+       /* of the algorithms block size */
+       plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+       ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+                       plaintext_pad_len, 10);
+       ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+                       plaintext_pad_len, 3);
+
+       /* Append data which is padded to a multiple */
+       /* of the algorithms block size */
+       pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+       /* Create KASUMI operation */
+       retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+                                       tdata->iv.len,
+                                       tdata->plaintext.len,
+                                       tdata->validCipherOffsetLenInBits.len,
+                                       RTE_CRYPTO_CIPHER_KASUMI_F8);
+       if (retval < 0)
+               return retval;
+
+       ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+                                               ut_params->op);
+       TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+       ut_params->obuf = ut_params->op->sym->m_dst;
+       if (ut_params->obuf)
+               ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+                               plaintext_pad_len, buffer);
+       else
+               ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+                               plaintext_pad_len, buffer);
+
+       /* Validate obuf */
+       TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+               ciphertext,
+               tdata->ciphertext.data,
+               tdata->validCipherLenInBits.len,
+               "KASUMI Ciphertext data not as expected");
+       return 0;
+}
+
+
+static int
 test_kasumi_decryption_oop(const struct kasumi_test_data *tdata)
 {
        struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -2849,6 +3006,85 @@ struct crypto_unittest_params {
        return 0;
 }
 
+static int
+test_snow3g_encryption_oop_sgl(const struct snow3g_test_data *tdata)
+{
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+       struct crypto_unittest_params *ut_params = &unittest_params;
+
+       int retval;
+       unsigned plaintext_pad_len;
+       unsigned plaintext_len;
+       uint8_t buffer[10000];
+       const uint8_t *ciphertext;
+
+       struct rte_cryptodev_info dev_info;
+
+       rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+       if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+               printf("Device doesn't support scatter-gather. "
+                               "Test Skipped.\n");
+               return 0;
+       }
+
+       /* Create SNOW 3G session */
+       retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+                                       RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+                                       RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+                                       tdata->key.data, tdata->key.len);
+       if (retval < 0)
+               return retval;
+
+       plaintext_len = ceil_byte_length(tdata->plaintext.len);
+       /* Append data which is padded to a multiple of */
+       /* the algorithms block size */
+       plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+       ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+                       plaintext_pad_len, 10);
+       ut_params->obuf = create_segmented_mbuf(ts_params->mbuf_pool,
+                       plaintext_pad_len, 3);
+
+       TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+                       "Failed to allocate input buffer in mempool");
+       TEST_ASSERT_NOT_NULL(ut_params->obuf,
+                       "Failed to allocate output buffer in mempool");
+
+       pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+       /* Create SNOW 3G operation */
+       retval = create_wireless_algo_cipher_operation_oop(tdata->iv.data,
+                                       tdata->iv.len,
+                                       tdata->validCipherLenInBits.len,
+                                       tdata->validCipherOffsetLenInBits.len,
+                                       RTE_CRYPTO_CIPHER_SNOW3G_UEA2);
+       if (retval < 0)
+               return retval;
+
+       ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+                                               ut_params->op);
+       TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+       ut_params->obuf = ut_params->op->sym->m_dst;
+       if (ut_params->obuf)
+               ciphertext = rte_pktmbuf_read(ut_params->obuf, tdata->iv.len,
+                               plaintext_len, buffer);
+       else
+               ciphertext = rte_pktmbuf_read(ut_params->ibuf, tdata->iv.len,
+                               plaintext_len, buffer);
+
+       TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+       /* Validate obuf */
+       TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+               ciphertext,
+               tdata->ciphertext.data,
+               tdata->validDataLenInBits.len,
+               "SNOW 3G Ciphertext data not as expected");
+
+       return 0;
+}
+
 /* Shift right a buffer by "offset" bits, "offset" < 8 */
 static void
 buffer_shift_right(uint8_t *buffer, uint32_t length, uint8_t offset)
@@ -3504,6 +3740,84 @@ static int test_snow3g_decryption_oop(const struct 
snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_sgl(const struct zuc_test_data *tdata)
+{
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+       struct crypto_unittest_params *ut_params = &unittest_params;
+
+       int retval;
+
+       unsigned plaintext_pad_len;
+       unsigned plaintext_len;
+       const uint8_t *ciphertext;
+       uint8_t ciphertext_buffer[2048];
+       struct rte_cryptodev_info dev_info;
+
+       rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+       if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+               printf("Device doesn't support scatter-gather. "
+                               "Test Skipped.\n");
+               return 0;
+       }
+
+       plaintext_len = ceil_byte_length(tdata->plaintext.len);
+
+       /* Append data which is padded to a multiple */
+       /* of the algorithms block size */
+       plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 8);
+
+       ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+                       plaintext_pad_len, 10);
+
+       pktmbuf_write(ut_params->ibuf, 0, plaintext_len,
+                       tdata->plaintext.data);
+
+       /* Create ZUC session */
+       retval = create_wireless_algo_cipher_session(ts_params->valid_devs[0],
+                       RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+                       RTE_CRYPTO_CIPHER_ZUC_EEA3,
+                       tdata->key.data, tdata->key.len);
+       if (retval < 0)
+               return retval;
+
+       /* Clear mbuf payload */
+
+       pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+       /* Create ZUC operation */
+       retval = create_wireless_algo_cipher_operation(tdata->iv.data,
+                       tdata->iv.len, tdata->plaintext.len,
+                       tdata->validCipherOffsetLenInBits.len,
+                       RTE_CRYPTO_CIPHER_ZUC_EEA3);
+       if (retval < 0)
+               return retval;
+
+       ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+                                               ut_params->op);
+       TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
+
+       ut_params->obuf = ut_params->op->sym->m_dst;
+       if (ut_params->obuf)
+               ciphertext = rte_pktmbuf_read(ut_params->obuf,
+                       tdata->iv.len, plaintext_len, ciphertext_buffer);
+       else
+               ciphertext = rte_pktmbuf_read(ut_params->ibuf,
+                       tdata->iv.len, plaintext_len, ciphertext_buffer);
+
+       /* Validate obuf */
+       TEST_HEXDUMP(stdout, "ciphertext:", ciphertext, plaintext_len);
+
+       /* Validate obuf */
+       TEST_ASSERT_BUFFERS_ARE_EQUAL_BIT(
+               ciphertext,
+               tdata->ciphertext.data,
+               tdata->validCipherLenInBits.len,
+               "ZUC Ciphertext data not as expected");
+
+       return 0;
+}
+
+static int
 test_zuc_authentication(const struct zuc_hash_test_data *tdata)
 {
        struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -3571,12 +3885,24 @@ static int test_snow3g_decryption_oop(const struct 
snow3g_test_data *tdata)
 }
 
 static int
+test_kasumi_encryption_test_case_1_sgl(void)
+{
+       return test_kasumi_encryption_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_1_oop(void)
 {
        return test_kasumi_encryption_oop(&kasumi_test_case_1);
 }
 
 static int
+test_kasumi_encryption_test_case_1_oop_sgl(void)
+{
+       return test_kasumi_encryption_oop_sgl(&kasumi_test_case_1);
+}
+
+static int
 test_kasumi_encryption_test_case_2(void)
 {
        return test_kasumi_encryption(&kasumi_test_case_2);
@@ -3648,6 +3974,13 @@ static int test_snow3g_decryption_oop(const struct 
snow3g_test_data *tdata)
 }
 
 static int
+test_snow3g_encryption_test_case_1_oop_sgl(void)
+{
+       return test_snow3g_encryption_oop_sgl(&snow3g_test_case_1);
+}
+
+
+static int
 test_snow3g_encryption_test_case_1_offset_oop(void)
 {
        return test_snow3g_encryption_offset_oop(&snow3g_test_case_1);
@@ -3767,6 +4100,12 @@ static int test_snow3g_decryption_oop(const struct 
snow3g_test_data *tdata)
 }
 
 static int
+test_zuc_encryption_test_case_6_sgl(void)
+{
+       return test_zuc_encryption_sgl(&zuc_test_case_1);
+}
+
+static int
 test_zuc_hash_generate_test_case_1(void)
 {
        return test_zuc_authentication(&zuc_hash_test_case_1);
@@ -4085,6 +4424,104 @@ static int test_snow3g_decryption_oop(const struct 
snow3g_test_data *tdata)
 }
 
 static int
+test_mb_AES_GCM_authenticated_encryption_sgl(const struct gcm_test_data *tdata)
+{
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+       struct crypto_unittest_params *ut_params = &unittest_params;
+       int retval;
+
+       unsigned plaintext_len;
+       uint16_t plaintext_pad_len;
+       uint8_t ciphertext_buffer[2048], auth_tag_buffer[2048];
+       const uint8_t *ciphertext, *auth_tag;
+
+       struct rte_cryptodev_info dev_info;
+
+       rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+       if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+               printf("Device doesn't support scatter-gather. "
+                               "Test Skipped.\n");
+               return 0;
+       }
+
+       /* Create GCM session */
+       retval = create_gcm_session(ts_params->valid_devs[0],
+                       RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+                       tdata->key.data, tdata->key.len,
+                       tdata->aad.len, tdata->auth_tag.len,
+                       RTE_CRYPTO_AUTH_OP_GENERATE);
+       if (retval < 0)
+               return retval;
+
+       plaintext_len = tdata->plaintext.len;
+
+       /* Append data which is padded to a multiple */
+       /* of the algorithms block size */
+       plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
+
+       ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
+                       plaintext_pad_len, 10);
+       pktmbuf_write(ut_params->ibuf, 0, plaintext_len, tdata->plaintext.data);
+
+       /* Create GCM opertaion */
+       retval = create_gcm_operation(RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+                       tdata->auth_tag.data, tdata->auth_tag.len,
+                       tdata->iv.data, tdata->iv.len,
+                       tdata->aad.data, tdata->aad.len,
+                       tdata->plaintext.len, plaintext_pad_len);
+       if (retval < 0) {
+               printf("create operation failed\n");
+               return retval;
+       }
+
+       rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess);
+
+       ut_params->op->sym->m_src = ut_params->ibuf;
+
+       /* Process crypto operation */
+       TEST_ASSERT_NOT_NULL(process_crypto_request(ts_params->valid_devs[0],
+                       ut_params->op), "failed to process sym crypto op");
+
+       TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+                       "crypto op processing failed");
+
+       /* Validate obuf */
+       if (ut_params->op->sym->m_dst) {
+               ciphertext = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+                               tdata->iv.len, plaintext_pad_len,
+                               ciphertext_buffer);
+               auth_tag = rte_pktmbuf_read(ut_params->op->sym->m_dst,
+                               plaintext_pad_len, tdata->auth_tag.len,
+                               auth_tag_buffer);
+       } else {
+               ciphertext = rte_pktmbuf_read(ut_params->op->sym->m_src,
+                               RTE_ALIGN_CEIL(tdata->iv.len, 16) +
+                               ALIGN_POW2_ROUNDUP(tdata->aad.len, 16),
+                               plaintext_pad_len, ciphertext_buffer);
+               auth_tag = rte_pktmbuf_read(ut_params->op->sym->m_src,
+                               plaintext_pad_len +
+                               RTE_ALIGN_CEIL(tdata->iv.len, 16) +
+                               ALIGN_POW2_ROUNDUP(tdata->aad.len, 16),
+                               tdata->auth_tag.len, auth_tag_buffer);
+       }
+
+       TEST_ASSERT_BUFFERS_ARE_EQUAL(
+                       ciphertext,
+                       tdata->ciphertext.data,
+                       tdata->ciphertext.len,
+                       "GCM Ciphertext data not as expected");
+
+       TEST_ASSERT_BUFFERS_ARE_EQUAL(
+                       auth_tag,
+                       tdata->auth_tag.data,
+                       tdata->auth_tag.len,
+                       "GCM Generated auth tag not as expected");
+
+       return 0;
+
+}
+
+static int
 test_mb_AES_GCM_authenticated_encryption_test_case_1(void)
 {
        return test_mb_AES_GCM_authenticated_encryption(&gcm_test_case_1);
@@ -4127,6 +4564,12 @@ static int test_snow3g_decryption_oop(const struct 
snow3g_test_data *tdata)
 }
 
 static int
+test_mb_AES_GCM_authenticated_encryption_test_case_8(void)
+{
+       return test_mb_AES_GCM_authenticated_encryption_sgl(&gcm_test_case_2);
+}
+
+static int
 test_mb_AES_GCM_authenticated_decryption(const struct gcm_test_data *tdata)
 {
        struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -6297,6 +6740,9 @@ struct test_crypto_vector {
                        test_mb_AES_GCM_authenticated_encryption_test_case_6),
                TEST_CASE_ST(ut_setup, ut_teardown,
                        test_mb_AES_GCM_authenticated_encryption_test_case_7),
+                       /** chained mbuf encrypt tests **/
+               TEST_CASE_ST(ut_setup, ut_teardown,
+                       test_mb_AES_GCM_authenticated_encryption_test_case_8),
 
                /** AES GCM Authenticated Decryption */
                TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6327,6 +6773,8 @@ struct test_crypto_vector {
                TEST_CASE_ST(ut_setup, ut_teardown,
                        test_kasumi_encryption_test_case_1),
                TEST_CASE_ST(ut_setup, ut_teardown,
+                       test_kasumi_encryption_test_case_1_sgl),
+               TEST_CASE_ST(ut_setup, ut_teardown,
                        test_kasumi_encryption_test_case_2),
                TEST_CASE_ST(ut_setup, ut_teardown,
                        test_kasumi_encryption_test_case_3),
@@ -6349,6 +6797,10 @@ struct test_crypto_vector {
                TEST_CASE_ST(ut_setup, ut_teardown,
                        test_kasumi_encryption_test_case_1_oop),
                TEST_CASE_ST(ut_setup, ut_teardown,
+                       test_kasumi_encryption_test_case_1_oop_sgl),
+
+
+               TEST_CASE_ST(ut_setup, ut_teardown,
                        test_kasumi_decryption_test_case_1_oop),
 
                /** KASUMI hash only (UIA1) */
@@ -6401,6 +6853,8 @@ struct test_crypto_vector {
                TEST_CASE_ST(ut_setup, ut_teardown,
                        test_snow3g_encryption_test_case_1_oop),
                TEST_CASE_ST(ut_setup, ut_teardown,
+                               test_snow3g_encryption_test_case_1_oop_sgl),
+               TEST_CASE_ST(ut_setup, ut_teardown,
                        test_snow3g_decryption_test_case_1_oop),
 
                TEST_CASE_ST(ut_setup, ut_teardown,
@@ -6478,6 +6932,8 @@ struct test_crypto_vector {
                        test_zuc_hash_generate_test_case_4),
                TEST_CASE_ST(ut_setup, ut_teardown,
                        test_zuc_hash_generate_test_case_5),
+               TEST_CASE_ST(ut_setup, ut_teardown,
+                       test_zuc_encryption_test_case_6_sgl),
                TEST_CASES_END() /**< NULL terminate unit test array */
        }
 };
diff --git a/app/test/test_cryptodev.h b/app/test/test_cryptodev.h
index a9089aa..f68ad0a 100644
--- a/app/test/test_cryptodev.h
+++ b/app/test/test_cryptodev.h
@@ -71,4 +71,115 @@
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA384            (24)
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA512            (32)
 
+/**
+ * Write (spread) data from buffer to mbuf data
+ *
+ * @param mbuf
+ *   Destination mbuf
+ * @param offset
+ *   Start offset in mbuf
+ * @param len
+ *   Number of bytes to copy
+ * @param buffer
+ *   Continuous source buffer
+ */
+static inline void
+pktmbuf_write(struct rte_mbuf *mbuf, int offset, int len, const uint8_t 
*buffer)
+{
+       int n = len;
+       int l;
+       struct rte_mbuf *m;
+       char *dst;
+
+       for (m = mbuf; (m != NULL) && (offset > m->data_len); m = m->next)
+               offset -= m->data_len;
+
+       l = m->data_len - offset;
+
+       /* copy data from first segment */
+       dst = rte_pktmbuf_mtod_offset(m, char *, offset);
+       if (len <= l) {
+               rte_memcpy(dst, buffer, len);
+               return;
+       }
+
+       rte_memcpy(dst, buffer, l);
+       buffer += l;
+       n -= l;
+
+       for (m = m->next; (m != NULL) && (n > 0); m = m->next) {
+               dst = rte_pktmbuf_mtod(m, char *);
+               l = m->data_len;
+               if (n < l) {
+                       rte_memcpy(dst, buffer, n);
+                       return;
+               }
+               rte_memcpy(dst, buffer, l);
+               buffer += l;
+               n -= l;
+       }
+}
+
+static inline struct rte_mbuf *
+create_segmented_mbuf(struct rte_mempool *mbuf_pool, int pkt_len,
+               int nb_segs) {
+
+       struct rte_mbuf *m = NULL, *mbuf = NULL;
+       uint8_t *dst;
+       int data_len = 0;
+       int i, size;
+       int t_len;
+
+       if (pkt_len < 1) {
+               printf("Packet size must be 1 or more (is %d)\n", pkt_len);
+               return NULL;
+       }
+
+       if (nb_segs < 1) {
+               printf("Number of segments must be 1 or more (is %d)\n",
+                               nb_segs);
+               return NULL;
+       }
+
+       t_len = pkt_len >= nb_segs ? pkt_len / nb_segs : 1;
+       size = pkt_len;
+
+       /* Create chained mbuf_src and fill it generated data */
+       for (i = 0; size > 0; i++) {
+
+               m = rte_pktmbuf_alloc(mbuf_pool);
+               if (i == 0)
+                       mbuf = m;
+
+               if (!m) {
+                       printf("Cannot create segment for source mbuf");
+                       goto fail;
+               }
+
+               /* Make sure if tailroom is zeroed */
+               memset(rte_pktmbuf_mtod(m, uint8_t *), 0,
+                               rte_pktmbuf_tailroom(m));
+
+               data_len = size > t_len ? t_len : size;
+               dst = (uint8_t *)rte_pktmbuf_append(m, data_len);
+               if (!dst) {
+                       printf("Cannot append %d bytes to the mbuf\n",
+                                       data_len);
+                       goto fail;
+               }
+
+               if (mbuf != m)
+                       rte_pktmbuf_chain(mbuf, m);
+
+               size -= data_len;
+
+       }
+       return mbuf;
+
+fail:
+       if (mbuf)
+               rte_pktmbuf_free(mbuf);
+       return NULL;
+}
+
 #endif /* TEST_CRYPTODEV_H_ */
diff --git a/app/test/test_cryptodev_aes_test_vectors.h 
b/app/test/test_cryptodev_aes_test_vectors.h
index 1c68f93..ed63c0a 100644
--- a/app/test/test_cryptodev_aes_test_vectors.h
+++ b/app/test/test_cryptodev_aes_test_vectors.h
@@ -883,6 +883,17 @@
                        BLOCKCIPHER_TEST_TARGET_PMD_QAT
        },
        {
+               .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+                               "Scatter Gather",
+               .test_data = &aes_test_data_4,
+               .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+               .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG,
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+                       BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+                       BLOCKCIPHER_TEST_TARGET_PMD_QAT
+
+       },
+       {
                .test_descr = "AES-128-CBC HMAC-SHA1 Decryption Digest "
                        "Verify",
                .test_data = &aes_test_data_4,
@@ -926,6 +937,17 @@
                        BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
        },
        {
+               .test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest "
+                               "Scatter Gather Sessionless",
+               .test_data = &aes_test_data_6,
+               .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+               .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS |
+                       BLOCKCIPHER_TEST_FEATURE_SG |
+                       BLOCKCIPHER_TEST_FEATURE_OOP,
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+                       BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+       },
+       {
                .test_descr = "AES-128-CBC HMAC-SHA512 Decryption Digest "
                        "Verify",
                .test_data = &aes_test_data_6,
@@ -1033,9 +1055,17 @@
                .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
        },
        {
-               .test_descr = "AES-192-CBC Encryption",
+               .test_descr = "AES-192-CBC",
+               .test_data = &aes_test_data_10,
+               .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+       },
+       {
+               .test_descr = "AES-192-CBC Encryption Scater gather",
                .test_data = &aes_test_data_10,
                .op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+               .feature_mask = BLOCKCIPHER_TEST_FEATURE_SG |
+                       BLOCKCIPHER_TEST_FEATURE_OOP,
                .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
        },
        {
diff --git a/app/test/test_cryptodev_blockcipher.c 
b/app/test/test_cryptodev_blockcipher.c
index 37b10cf..9933ca3 100644
--- a/app/test/test_cryptodev_blockcipher.c
+++ b/app/test/test_cryptodev_blockcipher.c
@@ -41,6 +41,7 @@
 #include <rte_cryptodev_pmd.h>
 
 #include "test.h"
+#include "test_cryptodev.h"
 #include "test_cryptodev_blockcipher.h"
 #include "test_cryptodev_aes_test_vectors.h"
 #include "test_cryptodev_des_test_vectors.h"
@@ -63,6 +64,7 @@
        struct rte_crypto_sym_op *sym_op = NULL;
        struct rte_crypto_op *op = NULL;
        struct rte_cryptodev_sym_session *sess = NULL;
+       struct rte_cryptodev_info dev_info;
 
        int status = TEST_SUCCESS;
        const struct blockcipher_test_data *tdata = t->test_data;
@@ -72,6 +74,19 @@
        uint32_t digest_len = 0;
        char *buf_p = NULL;
 
+       int nb_segs = 3;
+       int nb_segs_oop = 1;
+
+       if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+               rte_cryptodev_info_get(dev_id, &dev_info);
+               if (!(dev_info.feature_flags &
+                               RTE_CRYPTODEV_FF_MBUF_SCATTER_GATHER)) {
+                       printf("Device doesn't support scatter-gather. "
+                                       "Test Skipped.\n");
+                       return 0;
+               }
+       }
+
        if (tdata->cipher_key.len)
                memcpy(cipher_key, tdata->cipher_key.data,
                        tdata->cipher_key.len);
@@ -96,72 +111,112 @@
        }
 
        /* preparing data */
-       ibuf = rte_pktmbuf_alloc(mbuf_pool);
-       if (!ibuf) {
-               snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-                       "line %u FAILED: %s",
-                       __LINE__, "Allocation of rte_mbuf failed");
-               status = TEST_FAILED;
-               goto error_exit;
-       }
 
-       if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
-               buf_len += tdata->iv.len;
-       if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
-               buf_len += digest_len;
+       if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
 
-       buf_p = rte_pktmbuf_append(ibuf, buf_len);
-       if (!buf_p) {
-               snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
-                       "line %u FAILED: %s",
-                       __LINE__, "No room to append mbuf");
-               status = TEST_FAILED;
-               goto error_exit;
-       }
-
-       if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-               rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
-               buf_p += tdata->iv.len;
-       }
+               if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+                       ibuf = create_segmented_mbuf(mbuf_pool,
+                                       tdata->plaintext.len, nb_segs);
+                       pktmbuf_write(ibuf, 0, tdata->plaintext.len,
+                                       tdata->plaintext.data);
+               } else {
+                       ibuf = create_segmented_mbuf(mbuf_pool,
+                                       tdata->ciphertext.len, nb_segs);
+                       pktmbuf_write(ibuf, 0, tdata->ciphertext.len,
+                                       tdata->ciphertext.data);
+               }
 
-       /* only encryption requires plaintext.data input,
-        * decryption/(digest gen)/(digest verify) use ciphertext.data
-        * to be computed
-        */
-       if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
-               rte_memcpy(buf_p, tdata->plaintext.data,
-                       tdata->plaintext.len);
-               buf_p += tdata->plaintext.len;
-       } else {
-               rte_memcpy(buf_p, tdata->ciphertext.data,
-                       tdata->ciphertext.len);
-               buf_p += tdata->ciphertext.len;
-       }
+               if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+                       rte_memcpy(rte_pktmbuf_prepend(ibuf, tdata->iv.len),
+                                       tdata->iv.data, tdata->iv.len);
+               }
 
-       if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
-               rte_memcpy(buf_p, tdata->digest.data, digest_len);
-       else
-               memset(buf_p, 0, digest_len);
+               buf_p = rte_pktmbuf_append(ibuf, digest_len);
+               if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+                       rte_memcpy(buf_p, tdata->digest.data, digest_len);
+               else
+                       memset(buf_p, 0, digest_len);
 
-       if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
-               obuf = rte_pktmbuf_alloc(mbuf_pool);
-               if (!obuf) {
-                       snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-                               "FAILED: %s", __LINE__,
-                               "Allocation of rte_mbuf failed");
+       } else {
+               ibuf = rte_pktmbuf_alloc(mbuf_pool);
+               if (!ibuf) {
+                       snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+                                       "line %u FAILED: %s",
+                                       __LINE__,
+                                       "Allocation of rte_mbuf failed");
                        status = TEST_FAILED;
                        goto error_exit;
                }
 
-               buf_p = rte_pktmbuf_append(obuf, buf_len);
+               if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER)
+                       buf_len += tdata->iv.len;
+               if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH)
+                       buf_len += digest_len;
+
+               buf_p = rte_pktmbuf_append(ibuf, buf_len);
                if (!buf_p) {
-                       snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
-                               "FAILED: %s", __LINE__,
-                               "No room to append mbuf");
+                       snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+                                       "line %u FAILED: %s",
+                                       __LINE__, "No room to append mbuf");
                        status = TEST_FAILED;
                        goto error_exit;
                }
-               memset(buf_p, 0, buf_len);
+
+               if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
+                       rte_memcpy(buf_p, tdata->iv.data, tdata->iv.len);
+                       buf_p += tdata->iv.len;
+               }
+
+               /* only encryption requires plaintext.data input,
+                * decryption/(digest gen)/(digest verify) use ciphertext.data
+                * to be computed
+                */
+               if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
+                       rte_memcpy(buf_p, tdata->plaintext.data,
+                                       tdata->plaintext.len);
+                       buf_p += tdata->plaintext.len;
+               } else {
+                       rte_memcpy(buf_p, tdata->ciphertext.data,
+                                       tdata->ciphertext.len);
+                       buf_p += tdata->ciphertext.len;
+               }
+
+               if (t->op_mask & BLOCKCIPHER_TEST_OP_AUTH_VERIFY)
+                       rte_memcpy(buf_p, tdata->digest.data, digest_len);
+               else
+                       memset(buf_p, 0, digest_len);
+       }
+
+       if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
+               if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_SG) {
+                       obuf = create_segmented_mbuf(mbuf_pool, buf_len,
+                                       nb_segs_oop);
+                       if (!obuf) {
+                               snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+                                               "line %u FAILED: %s", __LINE__,
+                                               "Allocation of rte_mbuf 
failed");
+                               status = TEST_FAILED;
+                               goto error_exit;
+                       }
+               } else {
+                       obuf = rte_pktmbuf_alloc(mbuf_pool);
+                       if (!obuf) {
+                               snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+                                               "line %u FAILED: %s", __LINE__,
+                                               "Allocation of rte_mbuf 
failed");
+                               status = TEST_FAILED;
+                               goto error_exit;
+                       }
+                       buf_p = rte_pktmbuf_append(obuf, buf_len);
+                       if (!buf_p) {
+                               snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN,
+                                               "line %u FAILED: %s", __LINE__,
+                                               "No room to append mbuf");
+                               status = TEST_FAILED;
+                               goto error_exit;
+                       }
+                       memset(buf_p, 0, buf_len);
+               }
        }
 
        /* Generate Crypto op data structure */
@@ -176,7 +231,6 @@
        }
 
        sym_op = op->sym;
-
        sym_op->m_src = ibuf;
 
        if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
@@ -386,13 +440,10 @@
        }
 
        if (t->op_mask & BLOCKCIPHER_TEST_OP_CIPHER) {
-               uint8_t *crypto_res;
+               uint8_t buffer[2048];
                const uint8_t *compare_ref;
                uint32_t compare_len;
 
-               crypto_res = rte_pktmbuf_mtod_offset(iobuf, uint8_t *,
-                       tdata->iv.len);
-
                if (t->op_mask & BLOCKCIPHER_TEST_OP_ENCRYPT) {
                        compare_ref = tdata->ciphertext.data;
                        compare_len = tdata->ciphertext.len;
@@ -401,7 +452,8 @@
                        compare_len = tdata->plaintext.len;
                }
 
-               if (memcmp(crypto_res, compare_ref, compare_len)) {
+               if (memcmp(rte_pktmbuf_read(iobuf, tdata->iv.len, compare_len,
+                               buffer), compare_ref, compare_len)) {
                        snprintf(test_msg, BLOCKCIPHER_TEST_MSG_LEN, "line %u "
                                "FAILED: %s", __LINE__,
                                "Crypto data not as expected");
diff --git a/app/test/test_cryptodev_blockcipher.h 
b/app/test/test_cryptodev_blockcipher.h
index 04ff1ee..87a0683 100644
--- a/app/test/test_cryptodev_blockcipher.h
+++ b/app/test/test_cryptodev_blockcipher.h
@@ -45,6 +45,7 @@
 #define BLOCKCIPHER_TEST_FEATURE_OOP                   0x01
 #define BLOCKCIPHER_TEST_FEATURE_SESSIONLESS   0x02
 #define BLOCKCIPHER_TEST_FEATURE_STOPPER       0x04 /* stop upon failing */
+#define BLOCKCIPHER_TEST_FEATURE_SG            0x08 /* Scatter Gather */
 
 #define BLOCKCIPHER_TEST_TARGET_PMD_MB         0x0001 /* Multi-buffer flag */
 #define BLOCKCIPHER_TEST_TARGET_PMD_QAT                        0x0002 /* QAT 
flag */
-- 
1.7.9.5

Reply via email to