app/test: add ARMv8 crypto tests and test vectors
authorZbigniew Bodek <zbigniew.bodek@caviumnetworks.com>
Wed, 18 Jan 2017 20:02:01 +0000 (21:02 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Thu, 19 Jan 2017 00:00:55 +0000 (01:00 +0100)
Introduce unit tests for ARMv8 crypto PMD.
Add test vectors for short cases such as 160 bytes.
These test cases are ARMv8 specific since the code provides
different processing paths for different input data sizes.

User can validate correctness of algorithms' implementation using:
* cryptodev_sw_armv8_autotest
For performance test one can use:
* cryptodev_sw_armv8_perftest

Signed-off-by: Zbigniew Bodek <zbigniew.bodek@caviumnetworks.com>
Reviewed-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
app/test/test_cryptodev.c
app/test/test_cryptodev_aes_test_vectors.h
app/test/test_cryptodev_blockcipher.c
app/test/test_cryptodev_blockcipher.h
app/test/test_cryptodev_perf.c

index e8d1eae..0f0cf4d 100644 (file)
@@ -348,6 +348,28 @@ testsuite_setup(void)
                }
        }
 
+       /* Create 2 ARMv8 devices if required */
+       if (gbl_cryptodev_type == RTE_CRYPTODEV_ARMV8_PMD) {
+#ifndef RTE_LIBRTE_PMD_ARMV8_CRYPTO
+               RTE_LOG(ERR, USER1, "CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO must be"
+                       " enabled in config file to run this testsuite.\n");
+               return TEST_FAILED;
+#endif
+               nb_devs = rte_cryptodev_count_devtype(
+                               RTE_CRYPTODEV_ARMV8_PMD);
+               if (nb_devs < 2) {
+                       for (i = nb_devs; i < 2; i++) {
+                               ret = rte_eal_vdev_init(
+                                       RTE_STR(CRYPTODEV_NAME_ARMV8_PMD),
+                                       NULL);
+
+                               TEST_ASSERT(ret == 0, "Failed to create "
+                                       "instance %u of pmd : %s", i,
+                                       RTE_STR(CRYPTODEV_NAME_ARMV8_PMD));
+                       }
+               }
+       }
+
 #ifndef RTE_LIBRTE_PMD_QAT
        if (gbl_cryptodev_type == RTE_CRYPTODEV_QAT_SYM_PMD) {
                RTE_LOG(ERR, USER1, "CONFIG_RTE_LIBRTE_PMD_QAT must be enabled "
@@ -1593,6 +1615,22 @@ test_authonly_openssl_all(void)
        return TEST_SUCCESS;
 }
 
+static int
+test_AES_chain_armv8_all(void)
+{
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+       int status;
+
+       status = test_blockcipher_all_tests(ts_params->mbuf_pool,
+               ts_params->op_mpool, ts_params->valid_devs[0],
+               RTE_CRYPTODEV_ARMV8_PMD,
+               BLKCIPHER_AES_CHAIN_TYPE);
+
+       TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+       return TEST_SUCCESS;
+}
+
 /* ***** SNOW 3G Tests ***** */
 static int
 create_wireless_algo_hash_session(uint8_t dev_id,
@@ -7847,6 +7885,23 @@ static struct unit_test_suite cryptodev_null_testsuite  = {
        }
 };
 
+static struct unit_test_suite cryptodev_armv8_testsuite  = {
+       .suite_name = "Crypto Device ARMv8 Unit Test Suite",
+       .setup = testsuite_setup,
+       .teardown = testsuite_teardown,
+       .unit_test_cases = {
+               TEST_CASE_ST(ut_setup, ut_teardown, test_AES_chain_armv8_all),
+
+               /** Negative tests */
+               TEST_CASE_ST(ut_setup, ut_teardown,
+                       auth_decryption_AES128CBC_HMAC_SHA1_fail_data_corrupt),
+               TEST_CASE_ST(ut_setup, ut_teardown,
+                       auth_decryption_AES128CBC_HMAC_SHA1_fail_tag_corrupt),
+
+               TEST_CASES_END() /**< NULL terminate unit test array */
+       }
+};
+
 static int
 test_cryptodev_qat(void /*argv __rte_unused, int argc __rte_unused*/)
 {
@@ -7910,6 +7965,14 @@ test_cryptodev_sw_zuc(void /*argv __rte_unused, int argc __rte_unused*/)
        return unit_test_suite_runner(&cryptodev_sw_zuc_testsuite);
 }
 
+static int
+test_cryptodev_armv8(void)
+{
+       gbl_cryptodev_type = RTE_CRYPTODEV_ARMV8_PMD;
+
+       return unit_test_suite_runner(&cryptodev_armv8_testsuite);
+}
+
 REGISTER_TEST_COMMAND(cryptodev_qat_autotest, test_cryptodev_qat);
 REGISTER_TEST_COMMAND(cryptodev_aesni_mb_autotest, test_cryptodev_aesni_mb);
 REGISTER_TEST_COMMAND(cryptodev_openssl_autotest, test_cryptodev_openssl);
@@ -7918,3 +7981,4 @@ REGISTER_TEST_COMMAND(cryptodev_null_autotest, test_cryptodev_null);
 REGISTER_TEST_COMMAND(cryptodev_sw_snow3g_autotest, test_cryptodev_sw_snow3g);
 REGISTER_TEST_COMMAND(cryptodev_sw_kasumi_autotest, test_cryptodev_sw_kasumi);
 REGISTER_TEST_COMMAND(cryptodev_sw_zuc_autotest, test_cryptodev_sw_zuc);
+REGISTER_TEST_COMMAND(cryptodev_sw_armv8_autotest, test_cryptodev_armv8);
index e566548..f0f37ed 100644 (file)
@@ -825,6 +825,98 @@ static const struct blockcipher_test_data aes_test_data_11 = {
        }
 };
 
+/** AES-128-CBC SHA256 HMAC test vector (160 bytes) */
+static const struct blockcipher_test_data aes_test_data_12 = {
+       .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+       .cipher_key = {
+               .data = {
+                       0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+                       0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+               },
+               .len = 16
+       },
+       .iv = {
+               .data = {
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+               },
+               .len = 16
+       },
+       .plaintext = {
+               .data = plaintext_aes_common,
+               .len = 160
+       },
+       .ciphertext = {
+               .data = ciphertext512_aes128cbc,
+               .len = 160
+       },
+       .auth_algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+       .auth_key = {
+               .data = {
+                       0x42, 0x1A, 0x7D, 0x3D, 0xF5, 0x82, 0x80, 0xF1,
+                       0xF1, 0x35, 0x5C, 0x3B, 0xDD, 0x9A, 0x65, 0xBA,
+                       0x58, 0x34, 0x85, 0x61, 0x1C, 0x42, 0x10, 0x76,
+                       0x9A, 0x4F, 0x88, 0x1B, 0xB6, 0x8F, 0xD8, 0x60
+               },
+               .len = 32
+       },
+       .digest = {
+               .data = {
+                       0x92, 0xEC, 0x65, 0x9A, 0x52, 0xCC, 0x50, 0xA5,
+                       0xEE, 0x0E, 0xDF, 0x1E, 0xA4, 0xC9, 0xC1, 0x04,
+                       0xD5, 0xDC, 0x78, 0x90, 0xF4, 0xE3, 0x35, 0x62,
+                       0xAD, 0x95, 0x45, 0x28, 0x5C, 0xF8, 0x8C, 0x0B
+               },
+               .len = 32,
+               .truncated_len = 16
+       }
+};
+
+/** AES-128-CBC SHA1 HMAC test vector (160 bytes) */
+static const struct blockcipher_test_data aes_test_data_13 = {
+       .crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
+       .cipher_key = {
+               .data = {
+                       0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2,
+                       0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A
+               },
+               .len = 16
+       },
+       .iv = {
+               .data = {
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+               },
+               .len = 16
+       },
+       .plaintext = {
+               .data = plaintext_aes_common,
+               .len = 160
+       },
+       .ciphertext = {
+               .data = ciphertext512_aes128cbc,
+               .len = 160
+       },
+       .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+       .auth_key = {
+               .data = {
+                       0xF8, 0x2A, 0xC7, 0x54, 0xDB, 0x96, 0x18, 0xAA,
+                       0xC3, 0xA1, 0x53, 0xF6, 0x1F, 0x17, 0x60, 0xBD,
+                       0xDE, 0xF4, 0xDE, 0xAD
+               },
+               .len = 20
+       },
+       .digest = {
+               .data = {
+                       0x4F, 0x16, 0xEA, 0xF7, 0x4A, 0x88, 0xD3, 0xE0,
+                       0x0E, 0x12, 0x8B, 0xE7, 0x05, 0xD0, 0x86, 0x48,
+                       0x22, 0x43, 0x30, 0xA7
+               },
+               .len = 20,
+               .truncated_len = 12
+       }
+};
+
 static const struct blockcipher_test_case aes_chain_test_cases[] = {
        {
                .test_descr = "AES-128-CTR HMAC-SHA1 Encryption Digest",
@@ -888,10 +980,18 @@ static const struct blockcipher_test_case aes_chain_test_cases[] = {
                .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest",
                .test_data = &aes_test_data_4,
                .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
-               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8 |
+                       BLOCKCIPHER_TEST_TARGET_PMD_MB |
                        BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
                        BLOCKCIPHER_TEST_TARGET_PMD_QAT
        },
+       {
+               .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
+                       "(short buffers)",
+               .test_data = &aes_test_data_13,
+               .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8
+       },
        {
                .test_descr = "AES-128-CBC HMAC-SHA1 Encryption Digest "
                                "Scatter Gather",
@@ -902,34 +1002,57 @@ static const struct blockcipher_test_case aes_chain_test_cases[] = {
                .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,
                .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
-               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8 |
+                       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 (short buffers)",
+               .test_data = &aes_test_data_13,
+               .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8
+       },
        {
                .test_descr = "AES-128-CBC HMAC-SHA256 Encryption Digest",
                .test_data = &aes_test_data_5,
                .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
-               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8 |
+                       BLOCKCIPHER_TEST_TARGET_PMD_MB |
                        BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
                        BLOCKCIPHER_TEST_TARGET_PMD_QAT
        },
+       {
+               .test_descr = "AES-128-CBC HMAC-SHA256 Encryption Digest "
+                       "(short buffers)",
+               .test_data = &aes_test_data_12,
+               .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8
+       },
        {
                .test_descr = "AES-128-CBC HMAC-SHA256 Decryption Digest "
                        "Verify",
                .test_data = &aes_test_data_5,
                .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
-               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_MB |
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8 |
+                       BLOCKCIPHER_TEST_TARGET_PMD_MB |
                        BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
                        BLOCKCIPHER_TEST_TARGET_PMD_QAT
        },
+       {
+               .test_descr = "AES-128-CBC HMAC-SHA256 Decryption Digest "
+                       "Verify (short buffers)",
+               .test_data = &aes_test_data_12,
+               .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8
+       },
        {
                .test_descr = "AES-128-CBC HMAC-SHA512 Encryption Digest",
                .test_data = &aes_test_data_6,
@@ -998,7 +1121,8 @@ static const struct blockcipher_test_case aes_chain_test_cases[] = {
                .test_data = &aes_test_data_4,
                .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
                .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
-               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_QAT |
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8 |
+                       BLOCKCIPHER_TEST_TARGET_PMD_QAT |
                        BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
        },
        {
@@ -1007,7 +1131,8 @@ static const struct blockcipher_test_case aes_chain_test_cases[] = {
                .test_data = &aes_test_data_4,
                .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
                .feature_mask = BLOCKCIPHER_TEST_FEATURE_OOP,
-               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_QAT |
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8 |
+                       BLOCKCIPHER_TEST_TARGET_PMD_QAT |
                        BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
        },
        {
@@ -1050,7 +1175,8 @@ static const struct blockcipher_test_case aes_chain_test_cases[] = {
                .test_data = &aes_test_data_4,
                .op_mask = BLOCKCIPHER_TEST_OP_ENC_AUTH_GEN,
                .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS,
-               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8 |
+                       BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
        },
        {
                .test_descr =
@@ -1059,7 +1185,8 @@ static const struct blockcipher_test_case aes_chain_test_cases[] = {
                .test_data = &aes_test_data_4,
                .op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY_DEC,
                .feature_mask = BLOCKCIPHER_TEST_FEATURE_SESSIONLESS,
-               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+               .pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8 |
+                       BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
        },
 };
 
index 01aef3b..a48540c 100644 (file)
@@ -102,6 +102,7 @@ test_blockcipher_one_case(const struct blockcipher_test_case *t,
        switch (cryptodev_type) {
        case RTE_CRYPTODEV_QAT_SYM_PMD:
        case RTE_CRYPTODEV_OPENSSL_PMD:
+       case RTE_CRYPTODEV_ARMV8_PMD: /* Fall through */
                digest_len = tdata->digest.len;
                break;
        case RTE_CRYPTODEV_AESNI_MB_PMD:
@@ -645,6 +646,9 @@ test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
        case RTE_CRYPTODEV_OPENSSL_PMD:
                target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL;
                break;
+       case RTE_CRYPTODEV_ARMV8_PMD:
+               target_pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_ARMV8;
+               break;
        default:
                TEST_ASSERT(0, "Unrecognized cryptodev type");
                break;
index 7256f6b..91e9858 100644 (file)
@@ -50,6 +50,7 @@
 #define BLOCKCIPHER_TEST_TARGET_PMD_MB         0x0001 /* Multi-buffer flag */
 #define BLOCKCIPHER_TEST_TARGET_PMD_QAT                        0x0002 /* QAT flag */
 #define BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL    0x0004 /* SW OPENSSL flag */
+#define BLOCKCIPHER_TEST_TARGET_PMD_ARMV8      0x0008 /* ARMv8 flag */
 
 #define BLOCKCIPHER_TEST_OP_CIPHER     (BLOCKCIPHER_TEST_OP_ENCRYPT | \
                                        BLOCKCIPHER_TEST_OP_DECRYPT)
index 9b26fc1..7f1adf8 100644 (file)
@@ -157,6 +157,12 @@ test_perf_create_openssl_session(uint8_t dev_id, enum chain_mode chain,
                enum rte_crypto_cipher_algorithm cipher_algo,
                unsigned int cipher_key_len,
                enum rte_crypto_auth_algorithm auth_algo);
+static struct rte_cryptodev_sym_session *
+test_perf_create_armv8_session(uint8_t dev_id, enum chain_mode chain,
+               enum rte_crypto_cipher_algorithm cipher_algo,
+               unsigned int cipher_key_len,
+               enum rte_crypto_auth_algorithm auth_algo);
+
 static struct rte_mbuf *
 test_perf_create_pktmbuf(struct rte_mempool *mpool, unsigned buf_sz);
 static inline struct rte_crypto_op *
@@ -397,6 +403,28 @@ testsuite_setup(void)
                }
        }
 
+       /* Create 2 ARMv8 devices if required */
+       if (gbl_cryptodev_perftest_devtype == RTE_CRYPTODEV_ARMV8_PMD) {
+#ifndef RTE_LIBRTE_PMD_ARMV8_CRYPTO
+               RTE_LOG(ERR, USER1, "CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO must be"
+                       " enabled in config file to run this testsuite.\n");
+               return TEST_FAILED;
+#endif
+               nb_devs = rte_cryptodev_count_devtype(
+                               RTE_CRYPTODEV_ARMV8_PMD);
+               if (nb_devs < 2) {
+                       for (i = nb_devs; i < 2; i++) {
+                               ret = rte_eal_vdev_init(
+                                       RTE_STR(CRYPTODEV_NAME_ARMV8_PMD),
+                                       NULL);
+
+                               TEST_ASSERT(ret == 0, "Failed to create "
+                                       "instance %u of pmd : %s", i,
+                                       RTE_STR(CRYPTODEV_NAME_ARMV8_PMD));
+                       }
+               }
+       }
+
 #ifndef RTE_LIBRTE_PMD_QAT
        if (gbl_cryptodev_perftest_devtype == RTE_CRYPTODEV_QAT_SYM_PMD) {
                RTE_LOG(ERR, USER1, "CONFIG_RTE_LIBRTE_PMD_QAT must be enabled "
@@ -2425,6 +2453,139 @@ test_perf_openssl_optimise_cyclecount(struct perf_test_params *pparams)
        return TEST_SUCCESS;
 }
 
+static int
+test_perf_armv8_optimise_cyclecount(struct perf_test_params *pparams)
+{
+       uint32_t num_to_submit = pparams->total_operations;
+       struct rte_crypto_op *c_ops[num_to_submit];
+       struct rte_crypto_op *proc_ops[num_to_submit];
+       uint64_t failed_polls, retries, start_cycles, end_cycles,
+                total_cycles = 0;
+       uint32_t burst_sent = 0, burst_received = 0;
+       uint32_t i, burst_size, num_sent, num_ops_received;
+       uint32_t nb_ops;
+
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+       static struct rte_cryptodev_sym_session *sess;
+
+       unsigned int digest_length = get_auth_digest_length(pparams->auth_algo);
+
+       if (rte_cryptodev_count() == 0) {
+               printf("\nNo crypto devices found. Is PMD build configured?\n");
+               return TEST_FAILED;
+       }
+
+       /* Create Crypto session*/
+       sess = test_perf_create_armv8_session(ts_params->dev_id,
+                       pparams->chain, pparams->cipher_algo,
+                       pparams->cipher_key_length, pparams->auth_algo);
+       TEST_ASSERT_NOT_NULL(sess, "Session creation failed");
+
+       /* Generate Crypto op data structure(s)*/
+       for (i = 0; i < num_to_submit ; i++) {
+               struct rte_mbuf *m = test_perf_create_pktmbuf(
+                                               ts_params->mbuf_mp,
+                                               pparams->buf_size);
+               TEST_ASSERT_NOT_NULL(m, "Failed to allocate tx_buf");
+
+               struct rte_crypto_op *op =
+                               rte_crypto_op_alloc(ts_params->op_mpool,
+                                               RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+               TEST_ASSERT_NOT_NULL(op, "Failed to allocate op");
+
+               op = test_perf_set_crypto_op_aes(op, m, sess, pparams->buf_size,
+                               digest_length, pparams->chain);
+               TEST_ASSERT_NOT_NULL(op, "Failed to attach op to session");
+
+               c_ops[i] = op;
+       }
+
+       printf("\nOn %s dev%u qp%u, %s, cipher algo:%s, cipher key length:%u, "
+                       "auth_algo:%s, Packet Size %u bytes",
+                       pmd_name(gbl_cryptodev_perftest_devtype),
+                       ts_params->dev_id, 0,
+                       chain_mode_name(pparams->chain),
+                       cipher_algo_name(pparams->cipher_algo),
+                       pparams->cipher_key_length,
+                       auth_algo_name(pparams->auth_algo),
+                       pparams->buf_size);
+       printf("\nOps Tx\tOps Rx\tOps/burst  ");
+       printf("Retries  "
+               "EmptyPolls\tIACycles/CyOp\tIACycles/Burst\tIACycles/Byte");
+
+       for (i = 2; i <= 128 ; i *= 2) {
+               num_sent = 0;
+               num_ops_received = 0;
+               retries = 0;
+               failed_polls = 0;
+               burst_size = i;
+               total_cycles = 0;
+               while (num_sent < num_to_submit) {
+                       if ((num_to_submit - num_sent) < burst_size)
+                               nb_ops = num_to_submit - num_sent;
+                       else
+                               nb_ops = burst_size;
+
+                       start_cycles = rte_rdtsc();
+                       burst_sent = rte_cryptodev_enqueue_burst(
+                               ts_params->dev_id,
+                               0, &c_ops[num_sent],
+                               nb_ops);
+                       end_cycles = rte_rdtsc();
+
+                       if (burst_sent == 0)
+                               retries++;
+                       num_sent += burst_sent;
+                       total_cycles += (end_cycles - start_cycles);
+
+                       start_cycles = rte_rdtsc();
+                       burst_received = rte_cryptodev_dequeue_burst(
+                                       ts_params->dev_id, 0, proc_ops,
+                                       burst_size);
+                       end_cycles = rte_rdtsc();
+                       if (burst_received < burst_sent)
+                               failed_polls++;
+                       num_ops_received += burst_received;
+
+                       total_cycles += end_cycles - start_cycles;
+               }
+
+               while (num_ops_received != num_to_submit) {
+                       /* Sending 0 length burst to flush sw crypto device */
+                       rte_cryptodev_enqueue_burst(
+                                               ts_params->dev_id, 0, NULL, 0);
+
+                       start_cycles = rte_rdtsc();
+                       burst_received = rte_cryptodev_dequeue_burst(
+                               ts_params->dev_id, 0, proc_ops, burst_size);
+                       end_cycles = rte_rdtsc();
+
+                       total_cycles += end_cycles - start_cycles;
+                       if (burst_received == 0)
+                               failed_polls++;
+                       num_ops_received += burst_received;
+               }
+
+               printf("\n%u\t%u\t%u", num_sent, num_ops_received, burst_size);
+               printf("\t\t%"PRIu64, retries);
+               printf("\t%"PRIu64, failed_polls);
+               printf("\t\t%"PRIu64, total_cycles/num_ops_received);
+               printf("\t\t%"PRIu64,
+                       (total_cycles/num_ops_received)*burst_size);
+               printf("\t\t%"PRIu64,
+                       total_cycles/(num_ops_received*pparams->buf_size));
+       }
+       printf("\n");
+
+       for (i = 0; i < num_to_submit ; i++) {
+               rte_pktmbuf_free(c_ops[i]->sym->m_src);
+               rte_crypto_op_free(c_ops[i]);
+       }
+
+       return TEST_SUCCESS;
+}
+
 static uint32_t get_auth_key_max_length(enum rte_crypto_auth_algorithm algo)
 {
        switch (algo) {
@@ -2690,6 +2851,56 @@ test_perf_create_openssl_session(uint8_t dev_id, enum chain_mode chain,
        }
 }
 
+static struct rte_cryptodev_sym_session *
+test_perf_create_armv8_session(uint8_t dev_id, enum chain_mode chain,
+               enum rte_crypto_cipher_algorithm cipher_algo,
+               unsigned int cipher_key_len,
+               enum rte_crypto_auth_algorithm auth_algo)
+{
+       struct rte_crypto_sym_xform cipher_xform = { 0 };
+       struct rte_crypto_sym_xform auth_xform = { 0 };
+
+       /* Setup Cipher Parameters */
+       cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+       cipher_xform.cipher.algo = cipher_algo;
+
+       switch (cipher_algo) {
+       case RTE_CRYPTO_CIPHER_AES_CBC:
+               cipher_xform.cipher.key.data = aes_cbc_128_key;
+               break;
+       default:
+               return NULL;
+       }
+
+       cipher_xform.cipher.key.length = cipher_key_len;
+
+       /* Setup Auth Parameters */
+       auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+       auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
+       auth_xform.auth.algo = auth_algo;
+
+       auth_xform.auth.digest_length = get_auth_digest_length(auth_algo);
+
+       switch (chain) {
+       case CIPHER_HASH:
+               cipher_xform.next = &auth_xform;
+               auth_xform.next = NULL;
+               /* Encrypt and hash the result */
+               cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+               /* Create Crypto session*/
+               return rte_cryptodev_sym_session_create(dev_id, &cipher_xform);
+       case HASH_CIPHER:
+               auth_xform.next = &cipher_xform;
+               cipher_xform.next = NULL;
+               /* Hash encrypted message and decrypt */
+               cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+               /* Create Crypto session*/
+               return rte_cryptodev_sym_session_create(dev_id, &auth_xform);
+       default:
+               return NULL;
+       }
+}
+
 #define AES_BLOCK_SIZE 16
 #define AES_CIPHER_IV_LENGTH 16
 
@@ -3380,6 +3591,139 @@ test_perf_openssl(uint8_t dev_id, uint16_t queue_id,
        return TEST_SUCCESS;
 }
 
+static int
+test_perf_armv8(uint8_t dev_id, uint16_t queue_id,
+               struct perf_test_params *pparams)
+{
+       uint16_t i, k, l, m;
+       uint16_t j = 0;
+       uint16_t ops_unused = 0;
+       uint16_t burst_size;
+       uint16_t ops_needed;
+
+       uint64_t burst_enqueued = 0, total_enqueued = 0, burst_dequeued = 0;
+       uint64_t processed = 0, failed_polls = 0, retries = 0;
+       uint64_t tsc_start = 0, tsc_end = 0;
+
+       unsigned int digest_length = get_auth_digest_length(pparams->auth_algo);
+
+       struct rte_crypto_op *ops[pparams->burst_size];
+       struct rte_crypto_op *proc_ops[pparams->burst_size];
+
+       struct rte_mbuf *mbufs[pparams->burst_size * NUM_MBUF_SETS];
+
+       struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+       static struct rte_cryptodev_sym_session *sess;
+
+       if (rte_cryptodev_count() == 0) {
+               printf("\nNo crypto devices found. Is PMD build configured?\n");
+               return TEST_FAILED;
+       }
+
+       /* Create Crypto session*/
+       sess = test_perf_create_armv8_session(ts_params->dev_id,
+                       pparams->chain, pparams->cipher_algo,
+                       pparams->cipher_key_length, pparams->auth_algo);
+       TEST_ASSERT_NOT_NULL(sess, "Session creation failed");
+
+       /* Generate a burst of crypto operations */
+       for (i = 0; i < (pparams->burst_size * NUM_MBUF_SETS); i++) {
+               mbufs[i] = test_perf_create_pktmbuf(
+                               ts_params->mbuf_mp,
+                               pparams->buf_size);
+
+               if (mbufs[i] == NULL) {
+                       printf("\nFailed to get mbuf - freeing the rest.\n");
+                       for (k = 0; k < i; k++)
+                               rte_pktmbuf_free(mbufs[k]);
+                       return -1;
+               }
+       }
+
+       tsc_start = rte_rdtsc();
+
+       while (total_enqueued < pparams->total_operations) {
+               if ((total_enqueued + pparams->burst_size) <=
+                                       pparams->total_operations)
+                       burst_size = pparams->burst_size;
+               else
+                       burst_size = pparams->total_operations - total_enqueued;
+
+               ops_needed = burst_size - ops_unused;
+
+               if (ops_needed != rte_crypto_op_bulk_alloc(ts_params->op_mpool,
+                               RTE_CRYPTO_OP_TYPE_SYMMETRIC, ops, ops_needed)){
+                       printf("\nFailed to alloc enough ops, finish dequeuing "
+                               "and free ops below.");
+               } else {
+                       for (i = 0; i < ops_needed; i++)
+                               ops[i] = test_perf_set_crypto_op_aes(ops[i],
+                                       mbufs[i + (pparams->burst_size *
+                                               (j % NUM_MBUF_SETS))], sess,
+                                       pparams->buf_size, digest_length,
+                                       pparams->chain);
+
+                       /* enqueue burst */
+                       burst_enqueued = rte_cryptodev_enqueue_burst(dev_id,
+                                       queue_id, ops, burst_size);
+
+                       if (burst_enqueued < burst_size)
+                               retries++;
+
+                       ops_unused = burst_size - burst_enqueued;
+                       total_enqueued += burst_enqueued;
+               }
+
+               /* dequeue burst */
+               burst_dequeued = rte_cryptodev_dequeue_burst(dev_id, queue_id,
+                               proc_ops, pparams->burst_size);
+               if (burst_dequeued == 0)
+                       failed_polls++;
+               else {
+                       processed += burst_dequeued;
+
+                       for (l = 0; l < burst_dequeued; l++)
+                               rte_crypto_op_free(proc_ops[l]);
+               }
+               j++;
+       }
+
+       /* Dequeue any operations still in the crypto device */
+       while (processed < pparams->total_operations) {
+               /* Sending 0 length burst to flush sw crypto device */
+               rte_cryptodev_enqueue_burst(dev_id, queue_id, NULL, 0);
+
+               /* dequeue burst */
+               burst_dequeued = rte_cryptodev_dequeue_burst(dev_id, queue_id,
+                               proc_ops, pparams->burst_size);
+               if (burst_dequeued == 0)
+                       failed_polls++;
+               else {
+                       processed += burst_dequeued;
+
+                       for (m = 0; m < burst_dequeued; m++)
+                               rte_crypto_op_free(proc_ops[m]);
+               }
+       }
+
+       tsc_end = rte_rdtsc();
+
+       double ops_s = ((double)processed / (tsc_end - tsc_start))
+                                       * rte_get_tsc_hz();
+       double throughput = (ops_s * pparams->buf_size * NUM_MBUF_SETS)
+                                       / 1000000000;
+
+       printf("\t%u\t%6.2f\t%10.2f\t%8"PRIu64"\t%8"PRIu64, pparams->buf_size,
+                       ops_s / 1000000, throughput, retries, failed_polls);
+
+       for (i = 0; i < pparams->burst_size * NUM_MBUF_SETS; i++)
+               rte_pktmbuf_free(mbufs[i]);
+
+       printf("\n");
+       return TEST_SUCCESS;
+}
+
 /*
 
     perf_test_aes_sha("avx2", HASH_CIPHER, 16, CBC, SHA1);
@@ -3692,6 +4036,125 @@ test_perf_openssl_vary_burst_size(void)
        return 0;
 }
 
+static int
+test_perf_armv8_vary_pkt_size(void)
+{
+       unsigned int total_operations = 100000;
+       unsigned int burst_size = { 64 };
+       unsigned int buf_lengths[] = { 64, 128, 256, 512, 768, 1024, 1280, 1536,
+                       1792, 2048 };
+       uint8_t i, j;
+
+       struct perf_test_params params_set[] = {
+               {
+                       .chain = CIPHER_HASH,
+
+                       .cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+                       .cipher_key_length = 16,
+                       .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC
+               },
+               {
+                       .chain = HASH_CIPHER,
+
+                       .cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+                       .cipher_key_length = 16,
+                       .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC
+               },
+               {
+                       .chain = CIPHER_HASH,
+
+                       .cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+                       .cipher_key_length = 16,
+                       .auth_algo = RTE_CRYPTO_AUTH_SHA256_HMAC
+               },
+               {
+                       .chain = HASH_CIPHER,
+
+                       .cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+                       .cipher_key_length = 16,
+                       .auth_algo = RTE_CRYPTO_AUTH_SHA256_HMAC
+               },
+       };
+
+       for (i = 0; i < RTE_DIM(params_set); i++) {
+               params_set[i].total_operations = total_operations;
+               params_set[i].burst_size = burst_size;
+               printf("\n%s. cipher algo: %s auth algo: %s cipher key size=%u."
+                               " burst_size: %d ops\n",
+                               chain_mode_name(params_set[i].chain),
+                               cipher_algo_name(params_set[i].cipher_algo),
+                               auth_algo_name(params_set[i].auth_algo),
+                               params_set[i].cipher_key_length,
+                               burst_size);
+               printf("\nBuffer Size(B)\tOPS(M)\tThroughput(Gbps)\tRetries\t"
+                               "EmptyPolls\n");
+               for (j = 0; j < RTE_DIM(buf_lengths); j++) {
+                       params_set[i].buf_size = buf_lengths[j];
+                       test_perf_armv8(testsuite_params.dev_id, 0,
+                                                       &params_set[i]);
+               }
+       }
+
+       return 0;
+}
+
+static int
+test_perf_armv8_vary_burst_size(void)
+{
+       unsigned int total_operations = 4096;
+       uint16_t buf_lengths[] = { 64 };
+       uint8_t i, j;
+
+       struct perf_test_params params_set[] = {
+               {
+                       .chain = CIPHER_HASH,
+
+                       .cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+                       .cipher_key_length = 16,
+                       .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC
+               },
+               {
+                       .chain = HASH_CIPHER,
+
+                       .cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+                       .cipher_key_length = 16,
+                       .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC
+               },
+               {
+                       .chain = CIPHER_HASH,
+
+                       .cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+                       .cipher_key_length = 16,
+                       .auth_algo = RTE_CRYPTO_AUTH_SHA256_HMAC
+               },
+               {
+                       .chain = HASH_CIPHER,
+
+                       .cipher_algo  = RTE_CRYPTO_CIPHER_AES_CBC,
+                       .cipher_key_length = 16,
+                       .auth_algo = RTE_CRYPTO_AUTH_SHA256_HMAC
+               },
+       };
+
+       printf("\n\nStart %s.", __func__);
+       printf("\nThis Test measures the average IA cycle cost using a "
+                       "constant request(packet) size. ");
+       printf("Cycle cost is only valid when indicators show device is "
+                       "not busy, i.e. Retries and EmptyPolls = 0");
+
+       for (i = 0; i < RTE_DIM(params_set); i++) {
+               printf("\n");
+               params_set[i].total_operations = total_operations;
+
+               for (j = 0; j < RTE_DIM(buf_lengths); j++) {
+                       params_set[i].buf_size = buf_lengths[j];
+                       test_perf_armv8_optimise_cyclecount(&params_set[i]);
+               }
+       }
+
+       return 0;
+}
+
 static int
 test_perf_aes_cbc_vary_burst_size(void)
 {
@@ -4244,6 +4707,19 @@ static struct unit_test_suite cryptodev_openssl_testsuite  = {
        }
 };
 
+static struct unit_test_suite cryptodev_armv8_testsuite  = {
+       .suite_name = "Crypto Device ARMv8 Unit Test Suite",
+       .setup = testsuite_setup,
+       .teardown = testsuite_teardown,
+       .unit_test_cases = {
+               TEST_CASE_ST(ut_setup, ut_teardown,
+                               test_perf_armv8_vary_pkt_size),
+               TEST_CASE_ST(ut_setup, ut_teardown,
+                               test_perf_armv8_vary_burst_size),
+               TEST_CASES_END() /**< NULL terminate unit test array */
+       }
+};
+
 static int
 perftest_aesni_gcm_cryptodev(void)
 {
@@ -4300,6 +4776,14 @@ perftest_qat_continual_cryptodev(void)
        return unit_test_suite_runner(&cryptodev_qat_continual_testsuite);
 }
 
+static int
+perftest_sw_armv8_cryptodev(void /*argv __rte_unused, int argc __rte_unused*/)
+{
+       gbl_cryptodev_perftest_devtype = RTE_CRYPTODEV_ARMV8_PMD;
+
+       return unit_test_suite_runner(&cryptodev_armv8_testsuite);
+}
+
 REGISTER_TEST_COMMAND(cryptodev_aesni_mb_perftest, perftest_aesni_mb_cryptodev);
 REGISTER_TEST_COMMAND(cryptodev_qat_perftest, perftest_qat_cryptodev);
 REGISTER_TEST_COMMAND(cryptodev_sw_snow3g_perftest, perftest_sw_snow3g_cryptodev);
@@ -4309,3 +4793,5 @@ REGISTER_TEST_COMMAND(cryptodev_openssl_perftest,
                perftest_openssl_cryptodev);
 REGISTER_TEST_COMMAND(cryptodev_qat_continual_perftest,
                perftest_qat_continual_cryptodev);
+REGISTER_TEST_COMMAND(cryptodev_sw_armv8_perftest,
+               perftest_sw_armv8_cryptodev);