net/i40e: fix Tx descriptor status api
[dpdk.git] / doc / guides / prog_guide / cryptodev_lib.rst
index 81a6b1f..30f0bcf 100644 (file)
@@ -1,32 +1,5 @@
-..  BSD LICENSE
-    Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
-
-    Redistribution and use in source and binary forms, with or without
-    modification, are permitted provided that the following conditions
-    are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in
-    the documentation and/or other materials provided with the
-    distribution.
-    * Neither the name of Intel Corporation nor the names of its
-    contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2016-2017 Intel Corporation.
 
 Cryptography Device Library
 ===========================
@@ -70,6 +43,15 @@ From the command line using the --vdev EAL option
 
    --vdev  'crypto_aesni_mb0,max_nb_queue_pairs=2,max_nb_sessions=1024,socket_id=0'
 
+.. Note::
+
+   * If DPDK application requires multiple software crypto PMD devices then required
+     number of ``--vdev`` with appropriate libraries are to be added.
+
+   * An Application with crypto PMD instaces sharing the same library requires unique ID.
+
+   Example: ``--vdev  'crypto_aesni_mb0' --vdev  'crypto_aesni_mb1'``
+
 Our using the rte_vdev_init API within the application code.
 
 .. code-block:: c
@@ -317,6 +299,33 @@ directly from the devices processed queue, and for virtual device's from a
 enqueue call.
 
 
+Private data
+~~~~~~~~~~~~
+For session-based operations, the set and get API provides a mechanism for an
+application to store and retrieve the private data information stored along with
+the crypto session.
+
+For example, suppose an application is submitting a crypto operation with a session
+associated and wants to indicate private data information which is required to be
+used after completion of the crypto operation. In this case, the application can use
+the set API to set the private data and retrieve it using get API.
+
+.. code-block:: c
+
+       int rte_cryptodev_sym_session_set_private_data(
+               struct rte_cryptodev_sym_session *sess, void *data, uint16_t size);
+
+       void * rte_cryptodev_sym_session_get_private_data(
+               struct rte_cryptodev_sym_session *sess);
+
+
+For session-less mode, the private data information can be placed along with the
+``struct rte_crypto_op``. The ``rte_crypto_op::private_data_offset`` indicates the
+start of private data information. The offset is counted from the start of the
+rte_crypto_op including other crypto information such as the IVs (since there can
+be an IV also for authentication).
+
+
 Enqueue / Dequeue Burst APIs
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -445,12 +454,12 @@ mempool for all crypto devices (where the mempool object size is big
 enough to hold the private session of any crypto device), as well as having
 multiple session mempools of different sizes for better memory usage.
 
-An application can use ``rte_cryptodev_get_private_session_size()`` to
+An application can use ``rte_cryptodev_sym_get_private_session_size()`` to
 get the private session size of given crypto device. This function would allow
 an application to calculate the max device session size of all crypto devices
 to create a single session mempool.
 If instead an application creates multiple session mempools, the Crypto device
-framework also provides ``rte_cryptodev_get_header_session_size`` to get
+framework also provides ``rte_cryptodev_sym_get_header_session_size`` to get
 the size of an uninitialized session.
 
 Once the session mempools have been created, ``rte_cryptodev_sym_session_create()``
@@ -539,12 +548,12 @@ chain.
 
                 struct {
                     uint8_t *data;
-                    phys_addr_t phys_addr;
+                    rte_iova_t phys_addr;
                 } digest; /**< Digest parameters */
 
                 struct {
                     uint8_t *data;
-                    phys_addr_t phys_addr;
+                    rte_iova_t phys_addr;
                 } aad;
                 /**< Additional authentication parameters */
             } aead;
@@ -566,13 +575,219 @@ chain.
 
                     struct {
                         uint8_t *data;
-                        phys_addr_t phys_addr;
+                        rte_iova_t phys_addr;
                     } digest; /**< Digest parameters */
                 } auth;
             };
         };
     };
 
+Sample code
+-----------
+
+There are various sample applications that show how to use the cryptodev library,
+such as the L2fwd with Crypto sample application (L2fwd-crypto) and
+the IPSec Security Gateway application (ipsec-secgw).
+
+While these applications demonstrate how an application can be created to perform
+generic crypto operation, the required complexity hides the basic steps of
+how to use the cryptodev APIs.
+
+The following sample code shows the basic steps to encrypt several buffers
+with AES-CBC (although performing other crypto operations is similar),
+using one of the crypto PMDs available in DPDK.
+
+.. code-block:: c
+
+    /*
+     * Simple example to encrypt several buffers with AES-CBC using
+     * the Cryptodev APIs.
+     */
+
+    #define MAX_SESSIONS         1024
+    #define NUM_MBUFS            1024
+    #define POOL_CACHE_SIZE      128
+    #define BURST_SIZE           32
+    #define BUFFER_SIZE          1024
+    #define AES_CBC_IV_LENGTH    16
+    #define AES_CBC_KEY_LENGTH   16
+    #define IV_OFFSET            (sizeof(struct rte_crypto_op) + \
+                                 sizeof(struct rte_crypto_sym_op))
+
+    struct rte_mempool *mbuf_pool, *crypto_op_pool, *session_pool;
+    unsigned int session_size;
+    int ret;
+
+    /* Initialize EAL. */
+    ret = rte_eal_init(argc, argv);
+    if (ret < 0)
+        rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
+
+    uint8_t socket_id = rte_socket_id();
+
+    /* Create the mbuf pool. */
+    mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool",
+                                    NUM_MBUFS,
+                                    POOL_CACHE_SIZE,
+                                    0,
+                                    RTE_MBUF_DEFAULT_BUF_SIZE,
+                                    socket_id);
+    if (mbuf_pool == NULL)
+        rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
+
+    /*
+     * The IV is always placed after the crypto operation,
+     * so some private data is required to be reserved.
+     */
+    unsigned int crypto_op_private_data = AES_CBC_IV_LENGTH;
+
+    /* Create crypto operation pool. */
+    crypto_op_pool = rte_crypto_op_pool_create("crypto_op_pool",
+                                            RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+                                            NUM_MBUFS,
+                                            POOL_CACHE_SIZE,
+                                            crypto_op_private_data,
+                                            socket_id);
+    if (crypto_op_pool == NULL)
+        rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n");
+
+    /* Create the virtual crypto device. */
+    char args[128];
+    const char *crypto_name = "crypto_aesni_mb0";
+    snprintf(args, sizeof(args), "socket_id=%d", socket_id);
+    ret = rte_vdev_init(crypto_name, args);
+    if (ret != 0)
+        rte_exit(EXIT_FAILURE, "Cannot create virtual device");
+
+    uint8_t cdev_id = rte_cryptodev_get_dev_id(crypto_name);
+
+    /* Get private session data size. */
+    session_size = rte_cryptodev_sym_get_private_session_size(cdev_id);
+
+    /*
+     * Create session mempool, with two objects per session,
+     * one for the session header and another one for the
+     * private session data for the crypto device.
+     */
+    session_pool = rte_mempool_create("session_pool",
+                                    MAX_SESSIONS * 2,
+                                    session_size,
+                                    POOL_CACHE_SIZE,
+                                    0, NULL, NULL, NULL,
+                                    NULL, socket_id,
+                                    0);
+
+    /* Configure the crypto device. */
+    struct rte_cryptodev_config conf = {
+        .nb_queue_pairs = 1,
+        .socket_id = socket_id
+    };
+    struct rte_cryptodev_qp_conf qp_conf = {
+        .nb_descriptors = 2048
+    };
+
+    if (rte_cryptodev_configure(cdev_id, &conf) < 0)
+        rte_exit(EXIT_FAILURE, "Failed to configure cryptodev %u", cdev_id);
+
+    if (rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
+                            socket_id, session_pool) < 0)
+        rte_exit(EXIT_FAILURE, "Failed to setup queue pair\n");
+
+    if (rte_cryptodev_start(cdev_id) < 0)
+        rte_exit(EXIT_FAILURE, "Failed to start device\n");
+
+    /* Create the crypto transform. */
+    uint8_t cipher_key[16] = {0};
+    struct rte_crypto_sym_xform cipher_xform = {
+        .next = NULL,
+        .type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+        .cipher = {
+            .op = RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+            .algo = RTE_CRYPTO_CIPHER_AES_CBC,
+            .key = {
+                .data = cipher_key,
+                .length = AES_CBC_KEY_LENGTH
+            },
+            .iv = {
+                .offset = IV_OFFSET,
+                .length = AES_CBC_IV_LENGTH
+            }
+        }
+    };
+
+    /* Create crypto session and initialize it for the crypto device. */
+    struct rte_cryptodev_sym_session *session;
+    session = rte_cryptodev_sym_session_create(session_pool);
+    if (session == NULL)
+        rte_exit(EXIT_FAILURE, "Session could not be created\n");
+
+    if (rte_cryptodev_sym_session_init(cdev_id, session,
+                    &cipher_xform, session_pool) < 0)
+        rte_exit(EXIT_FAILURE, "Session could not be initialized "
+                    "for the crypto device\n");
+
+    /* Get a burst of crypto operations. */
+    struct rte_crypto_op *crypto_ops[BURST_SIZE];
+    if (rte_crypto_op_bulk_alloc(crypto_op_pool,
+                            RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+                            crypto_ops, BURST_SIZE) == 0)
+        rte_exit(EXIT_FAILURE, "Not enough crypto operations available\n");
+
+    /* Get a burst of mbufs. */
+    struct rte_mbuf *mbufs[BURST_SIZE];
+    if (rte_pktmbuf_alloc_bulk(mbuf_pool, mbufs, BURST_SIZE) < 0)
+        rte_exit(EXIT_FAILURE, "Not enough mbufs available");
+
+    /* Initialize the mbufs and append them to the crypto operations. */
+    unsigned int i;
+    for (i = 0; i < BURST_SIZE; i++) {
+        if (rte_pktmbuf_append(mbufs[i], BUFFER_SIZE) == NULL)
+            rte_exit(EXIT_FAILURE, "Not enough room in the mbuf\n");
+        crypto_ops[i]->sym->m_src = mbufs[i];
+    }
+
+    /* Set up the crypto operations. */
+    for (i = 0; i < BURST_SIZE; i++) {
+        struct rte_crypto_op *op = crypto_ops[i];
+        /* Modify bytes of the IV at the end of the crypto operation */
+        uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op, uint8_t *,
+                                                IV_OFFSET);
+
+        generate_random_bytes(iv_ptr, AES_CBC_IV_LENGTH);
+
+        op->sym->cipher.data.offset = 0;
+        op->sym->cipher.data.length = BUFFER_SIZE;
+
+        /* Attach the crypto session to the operation */
+        rte_crypto_op_attach_sym_session(op, session);
+    }
+
+    /* Enqueue the crypto operations in the crypto device. */
+    uint16_t num_enqueued_ops = rte_cryptodev_enqueue_burst(cdev_id, 0,
+                                            crypto_ops, BURST_SIZE);
+
+    /*
+     * Dequeue the crypto operations until all the operations
+     * are proccessed in the crypto device.
+     */
+    uint16_t num_dequeued_ops, total_num_dequeued_ops = 0;
+    do {
+        struct rte_crypto_op *dequeued_ops[BURST_SIZE];
+        num_dequeued_ops = rte_cryptodev_dequeue_burst(cdev_id, 0,
+                                        dequeued_ops, BURST_SIZE);
+        total_num_dequeued_ops += num_dequeued_ops;
+
+        /* Check if operation was processed successfully */
+        for (i = 0; i < num_dequeued_ops; i++) {
+            if (dequeued_ops[i]->status != RTE_CRYPTO_OP_STATUS_SUCCESS)
+                rte_exit(EXIT_FAILURE,
+                        "Some operations were not processed correctly");
+        }
+
+        rte_mempool_put_bulk(crypto_op_pool, (void **)dequeued_ops,
+                                            num_dequeued_ops);
+    } while (total_num_dequeued_ops < num_enqueued_ops);
+
 
 Asymmetric Cryptography
 -----------------------