From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8213045845; Thu, 22 Aug 2024 12:29:19 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 3FEDF42EA2; Thu, 22 Aug 2024 12:29:19 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 4E4B842E9D for ; Thu, 22 Aug 2024 12:29:17 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 47M8bRla025688; Thu, 22 Aug 2024 03:29:16 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=pfpt0220; bh=V OtpbeV+5arSX+Csr8R0GL/8KOeNhmDwxDB5oyqXMQc=; b=iWfnTS3QajKK+zIgy X2kMWev7hHZVdKhrs5kkbc9APWlI3UW2abOb6SZP2YnOJOyfGB7e2+6vOCP1NWMi JED9LkJWzMpVi9Kp8Mkb6K5nne73pET2lTNHkJn3pT+izDMPerC9X1tL1laRK40o 0XIZnLyufgJpjQUUVD+z7ts6M46rv2EwNn2wAcIIIPSFhud98OoUS9K47gUKabqX Xk2Aw9FhSn1bgwgJZWD6oSgFyX8PW2qLWYm8dchTGxmEPeIhscQO4nkHvuFmVNNF 3s0MEGXwsmTYl+bLO36YATZMKYMv2exQ1SldEDKyQYPzHh07ZESZDwu8T4OufJ8E zrxtw== Received: from dc5-exch05.marvell.com ([199.233.59.128]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 415aw2nd6f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 22 Aug 2024 03:29:16 -0700 (PDT) Received: from DC5-EXCH05.marvell.com (10.69.176.209) by DC5-EXCH05.marvell.com (10.69.176.209) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.4; Thu, 22 Aug 2024 03:29:14 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH05.marvell.com (10.69.176.209) with Microsoft SMTP Server id 15.2.1544.4 via Frontend Transport; Thu, 22 Aug 2024 03:29:14 -0700 Received: from localhost.localdomain (unknown [10.28.36.179]) by maili.marvell.com (Postfix) with ESMTP id BE21E3F707D; Thu, 22 Aug 2024 03:29:11 -0700 (PDT) From: Vidya Sagar Velumuri To: Akhil Goyal , Fan Zhang CC: , , , , , , Subject: [PATCH v1 3/3] test/crypto: add support for error recovery Date: Thu, 22 Aug 2024 03:28:56 -0700 Message-ID: <20240822102856.3965710-3-vvelumuri@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240822102856.3965710-1-vvelumuri@marvell.com> References: <20240822102856.3965710-1-vvelumuri@marvell.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-GUID: CDw1tjt0S4yIycGu6gqepimP8bWbtjtr X-Proofpoint-ORIG-GUID: CDw1tjt0S4yIycGu6gqepimP8bWbtjtr X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.28.16 definitions=2024-08-22_03,2024-08-19_03,2024-05-17_01 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add a callback for error recovery and register it with cryptodev. Add a unit test to verify the error recovery of cryptodev. The unit test generates an error by passing an mbuf to cryptodev allocated from heap memory. The registered callback will be called as part of error recovery. The unit test verifies the cryptodev recovery by testing a simple crypto operation. Signed-off-by: Vidya Sagar Velumuri diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c index c846b26ed1..bfbdb8b10a 100644 --- a/app/test/test_cryptodev.c +++ b/app/test/test_cryptodev.c @@ -71,6 +71,9 @@ #define IN_PLACE 0 #define OUT_OF_PLACE 1 +#define QP_DRAIN_TIMEOUT 100 +#define HW_ERR_RECOVER_TIMEOUT 500 + static int gbl_driver_id; static enum rte_security_session_action_type gbl_action_type = @@ -202,6 +205,81 @@ static struct crypto_unittest_params unittest_params; static bool enq_cb_called; static bool deq_cb_called; +enum cryptodev_err_state { + CRYPTODEV_ERR_CLEARED, + CRYPTODEV_ERR_TRIGGERED, + CRYPTODEV_ERR_UNRECOVERABLE, +}; + +static enum cryptodev_err_state crypto_err = CRYPTODEV_ERR_CLEARED; + +static void +test_cryptodev_error_cb(uint8_t dev_id, enum rte_cryptodev_event_type event, void *cb_arg) +{ + struct crypto_testsuite_params *ts_params = &testsuite_params; + uint16_t qp_id; + int ticks = 0; + int ret = 0; + + RTE_SET_USED(event); + RTE_SET_USED(cb_arg); + + for (qp_id = 0; qp_id < ts_params->conf.nb_queue_pairs; qp_id++) { + ret = rte_cryptodev_queue_pair_event_error_query(dev_id, qp_id); + if (ret) + break; + } + if (ret == 1) { + /* Wait for the queue to be completely drained */ + while (rte_cryptodev_qp_depth_used(dev_id, qp_id) != 0) { + rte_delay_ms(10); + ticks++; + if (ticks > QP_DRAIN_TIMEOUT) { + crypto_err = CRYPTODEV_ERR_UNRECOVERABLE; + return; + } + } + if (rte_cryptodev_queue_pair_reset(dev_id, qp_id, NULL, 0)) { + crypto_err = CRYPTODEV_ERR_UNRECOVERABLE; + return; + } + } + + crypto_err = CRYPTODEV_ERR_CLEARED; +} + +static struct rte_mbuf * +create_mbuf_from_heap(int pkt_len, uint8_t pattern) +{ + struct rte_mbuf *m = NULL; + uint8_t *dst; + + m = calloc(1, MBUF_SIZE); + if (m == NULL) { + printf("Cannot create mbuf from heap"); + return NULL; + } + + /* Set the default values to the mbuf */ + m->nb_segs = 1; + m->port = RTE_MBUF_PORT_INVALID; + m->buf_len = MBUF_SIZE - sizeof(struct rte_mbuf) - RTE_PKTMBUF_HEADROOM; + rte_pktmbuf_reset_headroom(m); + __rte_mbuf_sanity_check(m, 1); + + m->buf_addr = (char *)m + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM; + + memset(m->buf_addr, pattern, m->buf_len); + dst = (uint8_t *)rte_pktmbuf_append(m, pkt_len); + if (dst == NULL) { + printf("Cannot append %d bytes to the mbuf\n", pkt_len); + free(m); + return NULL; + } + + return m; +} + int process_sym_raw_dp_op(uint8_t dev_id, uint16_t qp_id, struct rte_crypto_op *op, uint8_t is_cipher, uint8_t is_auth, @@ -12868,6 +12946,172 @@ test_tls_1_3_record_proto_sgl_oop(void) #endif +static int +test_cryptodev_error_recover_helper_check(void) +{ + struct crypto_testsuite_params *ts_params = &testsuite_params; + struct rte_cryptodev_info dev_info; + uint64_t feat_flags; + int ret; + + rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info); + feat_flags = dev_info.feature_flags; + + /* Skip the test if queue pair reset is not supported */ + ret = rte_cryptodev_queue_pair_reset(ts_params->valid_devs[0], 0, NULL, 0); + if (ret == -ENOTSUP) + return TEST_SKIPPED; + + ret = rte_cryptodev_qp_depth_used(ts_params->valid_devs[0], 0); + if (ret == -ENOTSUP) + return TEST_SKIPPED; + + if (!(feat_flags & RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO) || + ((global_api_test_type == CRYPTODEV_RAW_API_TEST) && + !(dev_info.feature_flags & RTE_CRYPTODEV_FF_SYM_RAW_DP))) { + RTE_LOG(INFO, USER1, "Feature flag req for AES Cipheronly, testsuite not met\n"); + return TEST_SKIPPED; + } + + return 0; +} + +static int +test_cryptodev_error_recover_helper(uint8_t dev_id, const void *test_data, bool generate_err) +{ + struct crypto_testsuite_params *ts_params = &testsuite_params; + struct crypto_unittest_params *ut_params = &unittest_params; + const struct blockcipher_test_data *tdata = test_data; + uint8_t cipher_key[tdata->cipher_key.len]; + struct rte_crypto_sym_op *sym_op = NULL; + struct rte_crypto_op *op = NULL; + char *dst; + + memcpy(cipher_key, tdata->cipher_key.data, tdata->cipher_key.len); + ut_params->cipher_xform.next = NULL; + ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; + ut_params->cipher_xform.cipher.algo = tdata->crypto_algo; + ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; + ut_params->cipher_xform.cipher.key.data = cipher_key; + ut_params->cipher_xform.cipher.key.length = tdata->cipher_key.len; + ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET; + ut_params->cipher_xform.cipher.iv.length = tdata->iv.len; + + ut_params->sess = rte_cryptodev_sym_session_create(dev_id, &ut_params->cipher_xform, + ts_params->session_mpool); + TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed"); + + ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool, RTE_CRYPTO_OP_TYPE_SYMMETRIC); + TEST_ASSERT_NOT_NULL(ut_params->op, "Failed to allocate symmetric crypto op"); + + memcpy(rte_crypto_op_ctod_offset(ut_params->op, uint8_t *, IV_OFFSET), tdata->iv.data, + tdata->iv.len); + sym_op = ut_params->op->sym; + sym_op->cipher.data.offset = tdata->cipher_offset; + sym_op->cipher.data.length = tdata->ciphertext.len - tdata->cipher_offset; + + rte_crypto_op_attach_sym_session(ut_params->op, ut_params->sess); + + if (generate_err) { + ut_params->ibuf = create_mbuf_from_heap(tdata->ciphertext.len, 0); + if (ut_params->ibuf == NULL) + return TEST_FAILED; + crypto_err = CRYPTODEV_ERR_TRIGGERED; + } else { + ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool); + } + + /* clear mbuf payload */ + memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0, + rte_pktmbuf_tailroom(ut_params->ibuf)); + + dst = rte_pktmbuf_mtod_offset(ut_params->ibuf, char *, 0); + memcpy(dst, tdata->plaintext.data, tdata->plaintext.len); + + sym_op->m_src = ut_params->ibuf; + sym_op->m_dst = NULL; + + op = process_crypto_request(ts_params->valid_devs[0], ut_params->op); + + if (generate_err) { + free(ut_params->ibuf); + ut_params->ibuf = NULL; + if (op == NULL) { + rte_cryptodev_sym_session_free(ts_params->valid_devs[0], ut_params->sess); + ut_params->sess = NULL; + return TEST_SUCCESS; + } else { + return TEST_FAILED; + } + } + + TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS, + "crypto op processing failed"); + + TEST_ASSERT_BUFFERS_ARE_EQUAL(dst, tdata->ciphertext.data + tdata->cipher_offset, + tdata->ciphertext.len - tdata->cipher_offset, + "Data not as expected"); + + rte_cryptodev_sym_session_free(ts_params->valid_devs[0], ut_params->sess); + ut_params->sess = NULL; + + return TEST_SUCCESS; +} + +/* + * This unit test verifies the recovery of the cryptodev from any fatal error. + * It verifies a single test data multiple times in a iteration. It uses a flag and flips its value + * for every call to helper function. + * + * When the flag is set to 0, the helper function verifies the test data without generating any + * errors, i.e: verifies the default behaviour of the cryptodev. + * + * When the flag is set to 1, the helper function allocates a pointer from heap or non-DMAble + * memory and passes the pointer to cryptodev PMD inorder to generate a fatal error. Once the error + * is generated, it waits till the cryptodev is recoverd from the error. + * + * Iterates the above steps multiple times, to verify the error recovery of cryptodev and behaviour + * of cryptodev after the recovery. + */ +static int +test_cryptodev_verify_error_recover(const void *test_data) +{ + int ret = TEST_FAILED; + int i, num_itr = 5; + + ret = test_cryptodev_error_recover_helper_check(); + if (ret) + return ret; + + TEST_ASSERT_SUCCESS(rte_cryptodev_callback_register(p_testsuite_params->valid_devs[0], + RTE_CRYPTODEV_EVENT_ERROR, + test_cryptodev_error_cb, NULL), + "Failed to register Cryptodev callback"); + + for (i = 0; i < num_itr; i++) { + int ticks = 0; + + ret = test_cryptodev_error_recover_helper(p_testsuite_params->valid_devs[0], + test_data, false); + TEST_ASSERT_EQUAL(ret, TEST_SUCCESS, "encryption failed"); + + /* Generate Error */ + ret = test_cryptodev_error_recover_helper(p_testsuite_params->valid_devs[0], + test_data, true); + TEST_ASSERT_EQUAL(ret, TEST_SUCCESS, "encryption failed"); + + /* Wait till cryptodev recovered from error */ + while (crypto_err == CRYPTODEV_ERR_TRIGGERED) { + rte_delay_ms(10); + if (ticks++ > HW_ERR_RECOVER_TIMEOUT) + return TEST_FAILED; + } + } + TEST_ASSERT_EQUAL(crypto_err, CRYPTODEV_ERR_CLEARED, "cryptodev error recovery failed"); + + return ret; +} + static int test_AES_GCM_authenticated_encryption_test_case_1(void) { @@ -18442,6 +18686,8 @@ static struct unit_test_suite cryptodev_gen_testsuite = { TEST_CASE_ST(ut_setup, ut_teardown, test_stats), TEST_CASE_ST(ut_setup, ut_teardown, test_enq_callback_setup), TEST_CASE_ST(ut_setup, ut_teardown, test_deq_callback_setup), + TEST_CASE_NAMED_WITH_DATA("Verify cryptodev error recover", ut_setup, ut_teardown, + test_cryptodev_verify_error_recover, &aes_test_data_4), TEST_CASES_END() /**< NULL terminate unit test array */ } }; -- 2.25.1