From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 81890A0519; Fri, 3 Jul 2020 14:50:25 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 99F6F1DB95; Fri, 3 Jul 2020 14:49:56 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 22DA91DB8D for ; Fri, 3 Jul 2020 14:49:52 +0200 (CEST) IronPort-SDR: Boxx6A/A3XFEQKhHXTgoPd8yUR2QlIYXZG445Wj/WHnMpPeI7cYzKJKc3/Dpxn0eVn1QaVYnJo yMf1b04R/ZAg== X-IronPort-AV: E=McAfee;i="6000,8403,9670"; a="146228885" X-IronPort-AV: E=Sophos;i="5.75,308,1589266800"; d="scan'208";a="146228885" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 03 Jul 2020 05:49:52 -0700 IronPort-SDR: eyY8CeoJts5M1iS+Q77ZjhhK3eB94lsTQbVORsyFA98K+R7PFfamjeG4DWQkWED3nBsEEHFtww A1tsjJlVEoYA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,308,1589266800"; d="scan'208";a="278425971" Received: from silpixa00398673.ir.intel.com (HELO silpixa00398673.ger.corp.intel.com) ([10.237.223.136]) by orsmga003.jf.intel.com with ESMTP; 03 Jul 2020 05:49:50 -0700 From: Fan Zhang To: dev@dpdk.org Cc: fiona.trahe@intel.com, akhil.goyal@nxp.com, Fan Zhang Date: Fri, 3 Jul 2020 13:49:42 +0100 Message-Id: <20200703124942.29171-5-roy.fan.zhang@intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200703124942.29171-1-roy.fan.zhang@intel.com> References: <20200703110923.26452-1-roy.fan.zhang@intel.com> <20200703124942.29171-1-roy.fan.zhang@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-dev] [dpdk-dev v4 4/4] doc: add cryptodev direct APIs guide X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch updates programmer's guide to demonstrate the usage and limitations of cryptodev symmetric crypto data-path APIs. Signed-off-by: Fan Zhang --- doc/guides/prog_guide/cryptodev_lib.rst | 266 ++++++++++++++++++++++++ doc/guides/rel_notes/release_20_08.rst | 8 + 2 files changed, 274 insertions(+) diff --git a/doc/guides/prog_guide/cryptodev_lib.rst b/doc/guides/prog_guide/cryptodev_lib.rst index c14f750fa..9900a593a 100644 --- a/doc/guides/prog_guide/cryptodev_lib.rst +++ b/doc/guides/prog_guide/cryptodev_lib.rst @@ -861,6 +861,272 @@ using one of the crypto PMDs available in DPDK. num_dequeued_ops); } while (total_num_dequeued_ops < num_enqueued_ops); +Cryptodev Direct Symmetric Crypto Data-path APIs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Direct symmetric crypto data-path APIs are a set of APIs that especially +provided for Symmetric HW Crypto PMD that provides fast data-path +enqueue/dequeue operations. The direct data-path APIs take advantage of +existing Cryptodev APIs for device, queue pairs, and session management. In +addition the user are required to get the queue pair pointer data and function +pointers. The APIs are provided as an advanced feature as an alternative +to ``rte_cryptodev_enqueue_burst`` and ``rte_cryptodev_dequeue_burst``. The +APIs are designed for the user to develop close-to-native performance symmetric +crypto data-path implementation for their applications that do not necessarily +depend on cryptodev operations and cryptodev operation mempools, or mbufs. + +Cryptodev PMDs who supports this feature will have +``RTE_CRYPTODEV_FF_SYM_HW_DIRECT_API`` feature flag presented. The user uses +``rte_cryptodev_sym_get_hw_ops`` function call to get all the function pointers +for different enqueue and dequeue operations, plus the device specific +queue pair data. After the ``rte_crypto_hw_ops`` structure is properly set by +the driver, the user can use the function pointers and the queue data pointers +in the structure to enqueue and dequeue crypto jobs. + +To simply the enqueue APIs a symmetric job structure is defined: + +.. code-block:: c + + /** + * Asynchronous operation job descriptor. + * Used by HW crypto devices direct API call that supports such activity + **/ + struct rte_crypto_sym_job { + union { + /** + * When RTE_CRYPTO_HW_ENQ_FLAG_IS_SGL bit is set in flags, sgl + * field is used as input data. Otherwise data_iova is + * used. + **/ + rte_iova_t data_iova; + struct rte_crypto_sgl *sgl; + }; + union { + /** + * Different than cryptodev ops, all ofs and len fields have + * the unit of bytes (including Snow3G/Kasumi/Zuc. + **/ + struct { + uint32_t cipher_ofs; + uint32_t cipher_len; + } cipher_only; + struct { + uint32_t auth_ofs; + uint32_t auth_len; + rte_iova_t digest_iova; + } auth_only; + struct { + uint32_t aead_ofs; + uint32_t aead_len; + rte_iova_t tag_iova; + uint8_t *aad; + rte_iova_t aad_iova; + } aead; + struct { + uint32_t cipher_ofs; + uint32_t cipher_len; + uint32_t auth_ofs; + uint32_t auth_len; + rte_iova_t digest_iova; + } chain; + }; + uint8_t *iv; + rte_iova_t iv_iova; + }; + +Different than Cryptodev operation, the ``rte_crypto_sym_job`` structure +focuses only on the data field required for crypto PMD to execute a single job, +and is not supposed stored as opaque data. The user can freely allocate the +structure buffer from stack and reuse it to fill all jobs. + +To use the direct symmetric crypto APIs safely, the user has to carefully +set the correct fields in rte_crypto_sym_job structure, otherwise the +application or the system may crash. Also there are a few limitations to the +direct symmetric crypto APIs: + +* Only support in-place operations. +* APIs are NOT thread-safe. +* CANNOT mix the direct API's enqueue with rte_cryptodev_enqueue_burst, or + vice versa. + +The following sample code shows how to use Cryptodev direct API to process a +user defined frame with maximum 32 buffers with AES-CBC and HMAC-SHA chained +algorithm of a frame defined by user. + +See *DPDK API Reference* for details on each API definitions. + +.. code-block:: c + + #include + + #define FRAME_ELT_OK 0 + #define FRAME_ELT_FAIL 1 + #define FRAME_OK 0 + #define FRAME_SOME_ELT_ERROR 1 + #define FRAME_SIZE 32 + + /* Sample frame element struct */ + struct sample_frame_elt { + /* The status field of frame element */ + uint8_t status; + /* Pre-created and initialized cryptodev session */ + struct rte_cryptodev_sym_session *session; + union { + __rte_iova_t data; + struct rte_crypto_sgl sgl; + }; + uint32_t data_len; + __rte_iova_t digest; + uint8_t *iv; + uint8_t is_sgl; + }; + + /* Sample frame struct to describe up to 32 crypto jobs */ + struct sample_frame { + struct sample_frame_elt elts[FRAME_SIZE]; /**< All frame elements */ + uint32_t n_elts; /**< Number of elements */ + }; + + /* Global Cryptodev Direct API structure */ + static struct rte_crypto_hw_ops hw_ops; + + /* Initialization */ + static int + frame_operation_init( + uint8_t cryptodev_id, /**< Initialized cryptodev ID */ + uint16_t qp_id /**< Initialized queue pair ID */) + { + /* Get APIs */ + ret = rte_cryptodev_sym_get_hw_ops(cryptodev_id, qp_id, &hw_ops); + /* If the device does not support this feature or queue pair is not + initialized, return -1 */ + if (!ret) + return -1; + return 0; + } + + /* Frame enqueue function use direct AES-CBC-* + HMAC-SHA* API */ + static int + enqueue_frame_to_direct_api( + struct sample_frame *frame /**< Initialized user frame struct */) + { + struct rte_crypto_hw_ops hw_ops; + struct rte_crypto_sym_job job; + uint64_t drv_data, flags = 0; + uint32_t i; + int ret; + + /* Fill all sample frame element data into HW queue pair */ + for (i = 0; i < frame->n_elts; i++) { + struct sample_frame_elt *fe = &frame->elts[i]; + int ret; + + /* if it is the first element in the frame, set FIRST flag to + let the driver to know it is first frame and fill drv_data. */ + if (i == 0) + flags |= RTE_CRYPTO_HW_ENQ_FLAG_START; + else + flags &= ~RTE_CRYPTO_HW_ENQ_FLAG_START; + + /* if it is the last element in the frame, write LAST flag to + kick HW queue */ + if (i == frame->n_elts - 1) + flags |= RTE_CRYPTO_HW_ENQ_FLAG_LAST; + else + flags &= ~RTE_CRYPTO_HW_ENQ_FLAG_LAST; + + /* Fill the job data with frame element data */ + if (fe->is_sgl != 0) { + /* The buffer is a SGL buffer */ + job.sgl = &frame->sgl; + /* Set SGL flag */ + flags |= RTE_CRYPTO_HW_ENQ_FLAG_IS_SGL; + } else { + job.data_iova = fe->data; + /* Unset SGL flag in the job */ + flags &= ~RTE_CRYPTO_HW_ENQ_FLAG_IS_SGL; + } + + job.chain.cipher_ofs = job.chain.auth_ofs = 0; + job.chain.cipher_len = job.chain.auth_len = fe->data_len; + job.chain.digest_iova = fe->digest; + + job.iv = fe->iv; + + /* Call direct data-path enqueue chaining op API */ + ret = hw_ops.enqueue_chain(hw_ops.qp, fe->session, &job, + (void *frame), &drv_data, flags); + /** + * In case one element is failed to be enqueued, simply abandon + * enqueuing the whole frame. + **/ + if (!ret) + return -1; + + /** + * To this point the frame is enqueued. The job buffer can be + * safely reused for enqueuing next frame element. + **/ + } + + return 0; + } + + /** + * Sample function to write frame element status field based on + * driver returned operation result. The function return and parameter + * should follow the prototype rte_crpyto_hw_user_post_deq_cb_fn() in + * rte_cryptodev.h + **/ + static __rte_always_inline void + write_frame_elt_status(void *data, uint32_t index, uint8_t is_op_success) + { + struct sample_frame *frame = data; + frame->elts[index + 1].status = is_op_success ? FRAME_ELT_OK : + FRAME_ELT_FAIL; + } + + /* Frame dequeue function use direct dequeue API */ + static struct sample_frame * + dequeue_frame_with_direct_api(void) + { + struct sample_frame *ret_frame; + uint64_t flags, drv_data; + uint32_t n, n_fail, n_fail_first = 0; + int ret; + + /* Dequeue first job, which should have frame data stored in opaque */ + flags = RTE_CRYPTO_HW_DEQ_FLAG_START; + ret_frame = hw_ops.dequeue_one(hw_ops.qp, &drv_data, flags, &ret); + if (ret == 0) { + /* ret == 0, means it is still under processing */ + return NULL; + } else if (ret == 1) { + /* ret_frame is successfully retrieved, the ret stores the + operation result */ + ret_frame->elts[0].status = FRAME_ELT_OK; + } else { + ret_frame->elts[0].status = FRAME_ELT_FAIL; + n_fail_first = 1; + } + + /* Query if n_elts has been processed, if not return NULL */ + if (!hw_ops.query_processed(hw_ops.qp, frame->n_elts)) + return NULL; + + /* We are sure all elements have been processed, dequeue them all */ + flag = 0; + ret = hw_ops.dequeue_many(hw_ops.qp, &drv_data, (void *)ret_frame, + write_frame_elt_status, ret_frame->n_elts - 1, flag, &n_fail); + + if (n_fail + n_fail_first > 0) + ret_frame->status = FRAME_SOME_ELT_ERROR; + else + ret_frame->status = FRAME_OK; + + return ret_frame; + } + Asymmetric Cryptography ----------------------- diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst index 39064afbe..eb973693d 100644 --- a/doc/guides/rel_notes/release_20_08.rst +++ b/doc/guides/rel_notes/release_20_08.rst @@ -56,6 +56,14 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= + * **Add Cryptodev data-path APIs for no mbuf-centric data-path.** + + Cryptodev is added a set of data-path APIs that are not based on + cryptodev operations. The APIs are designed for external applications + or libraries that want to use cryptodev but their data-path + implementations are not mbuf-centric. QAT Symmetric PMD is also updated + to add the support to this API. + Removed Items ------------- -- 2.20.1