xref: /dpdk/doc/guides/prog_guide/cryptodev_lib.rst (revision 2717246ecd7d27125a346a2c5c55b53a9c251a93)
1..  SPDX-License-Identifier: BSD-3-Clause
2    Copyright(c) 2016-2017 Intel Corporation.
3
4Cryptography Device Library
5===========================
6
7The cryptodev library provides a Crypto device framework for management and
8provisioning of hardware and software Crypto poll mode drivers, defining generic
9APIs which support a number of different Crypto operations. The framework
10currently only supports cipher, authentication, chained cipher/authentication
11and AEAD symmetric Crypto operations.
12
13
14Design Principles
15-----------------
16
17The cryptodev library follows the same basic principles as those used in DPDKs
18Ethernet Device framework. The Crypto framework provides a generic Crypto device
19framework which supports both physical (hardware) and virtual (software) Crypto
20devices as well as a generic Crypto API which allows Crypto devices to be
21managed and configured and supports Crypto operations to be provisioned on
22Crypto poll mode driver.
23
24
25Device Management
26-----------------
27
28Device Creation
29~~~~~~~~~~~~~~~
30
31Physical Crypto devices are discovered during the PCI probe/enumeration of the
32EAL function which is executed at DPDK initialization, based on
33their PCI device identifier, each unique PCI BDF (bus/bridge, device,
34function). Specific physical Crypto devices, like other physical devices in DPDK
35can be white-listed or black-listed using the EAL command line options.
36
37Virtual devices can be created by two mechanisms, either using the EAL command
38line options or from within the application using an EAL API directly.
39
40From the command line using the --vdev EAL option
41
42.. code-block:: console
43
44   --vdev  'crypto_aesni_mb0,max_nb_queue_pairs=2,socket_id=0'
45
46.. Note::
47
48   * If DPDK application requires multiple software crypto PMD devices then required
49     number of ``--vdev`` with appropriate libraries are to be added.
50
51   * An Application with crypto PMD instaces sharing the same library requires unique ID.
52
53   Example: ``--vdev  'crypto_aesni_mb0' --vdev  'crypto_aesni_mb1'``
54
55Our using the rte_vdev_init API within the application code.
56
57.. code-block:: c
58
59   rte_vdev_init("crypto_aesni_mb",
60                     "max_nb_queue_pairs=2,socket_id=0")
61
62All virtual Crypto devices support the following initialization parameters:
63
64* ``max_nb_queue_pairs`` - maximum number of queue pairs supported by the device.
65* ``socket_id`` - socket on which to allocate the device resources on.
66
67
68Device Identification
69~~~~~~~~~~~~~~~~~~~~~
70
71Each device, whether virtual or physical is uniquely designated by two
72identifiers:
73
74- A unique device index used to designate the Crypto device in all functions
75  exported by the cryptodev API.
76
77- A device name used to designate the Crypto device in console messages, for
78  administration or debugging purposes. For ease of use, the port name includes
79  the port index.
80
81
82Device Configuration
83~~~~~~~~~~~~~~~~~~~~
84
85The configuration of each Crypto device includes the following operations:
86
87- Allocation of resources, including hardware resources if a physical device.
88- Resetting the device into a well-known default state.
89- Initialization of statistics counters.
90
91The rte_cryptodev_configure API is used to configure a Crypto device.
92
93.. code-block:: c
94
95   int rte_cryptodev_configure(uint8_t dev_id,
96                               struct rte_cryptodev_config *config)
97
98The ``rte_cryptodev_config`` structure is used to pass the configuration
99parameters for socket selection and number of queue pairs.
100
101.. code-block:: c
102
103    struct rte_cryptodev_config {
104        int socket_id;
105        /**< Socket to allocate resources on */
106        uint16_t nb_queue_pairs;
107        /**< Number of queue pairs to configure on device */
108    };
109
110
111Configuration of Queue Pairs
112~~~~~~~~~~~~~~~~~~~~~~~~~~~~
113
114Each Crypto devices queue pair is individually configured through the
115``rte_cryptodev_queue_pair_setup`` API.
116Each queue pairs resources may be allocated on a specified socket.
117
118.. code-block:: c
119
120    int rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
121                const struct rte_cryptodev_qp_conf *qp_conf,
122                int socket_id)
123
124    struct rte_cryptodev_qp_conf {
125        uint32_t nb_descriptors; /**< Number of descriptors per queue pair */
126    };
127
128
129Logical Cores, Memory and Queues Pair Relationships
130~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131
132The Crypto device Library as the Poll Mode Driver library support NUMA for when
133a processor’s logical cores and interfaces utilize its local memory. Therefore
134Crypto operations, and in the case of symmetric Crypto operations, the session
135and the mbuf being operated on, should be allocated from memory pools created
136in the local memory. The buffers should, if possible, remain on the local
137processor to obtain the best performance results and buffer descriptors should
138be populated with mbufs allocated from a mempool allocated from local memory.
139
140The run-to-completion model also performs better, especially in the case of
141virtual Crypto devices, if the Crypto operation and session and data buffer is
142in local memory instead of a remote processor's memory. This is also true for
143the pipe-line model provided all logical cores used are located on the same
144processor.
145
146Multiple logical cores should never share the same queue pair for enqueuing
147operations or dequeuing operations on the same Crypto device since this would
148require global locks and hinder performance. It is however possible to use a
149different logical core to dequeue an operation on a queue pair from the logical
150core which it was enqueued on. This means that a crypto burst enqueue/dequeue
151APIs are a logical place to transition from one logical core to another in a
152packet processing pipeline.
153
154
155Device Features and Capabilities
156---------------------------------
157
158Crypto devices define their functionality through two mechanisms, global device
159features and algorithm capabilities. Global devices features identify device
160wide level features which are applicable to the whole device such as
161the device having hardware acceleration or supporting symmetric Crypto
162operations,
163
164The capabilities mechanism defines the individual algorithms/functions which
165the device supports, such as a specific symmetric Crypto cipher,
166authentication operation or Authenticated Encryption with Associated Data
167(AEAD) operation.
168
169
170Device Features
171~~~~~~~~~~~~~~~
172
173Currently the following Crypto device features are defined:
174
175* Symmetric Crypto operations
176* Asymmetric Crypto operations
177* Chaining of symmetric Crypto operations
178* SSE accelerated SIMD vector operations
179* AVX accelerated SIMD vector operations
180* AVX2 accelerated SIMD vector operations
181* AESNI accelerated instructions
182* Hardware off-load processing
183
184
185Device Operation Capabilities
186~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
187
188Crypto capabilities which identify particular algorithm which the Crypto PMD
189supports are  defined by the operation type, the operation transform, the
190transform identifier and then the particulars of the transform. For the full
191scope of the Crypto capability see the definition of the structure in the
192*DPDK API Reference*.
193
194.. code-block:: c
195
196   struct rte_cryptodev_capabilities;
197
198Each Crypto poll mode driver defines its own private array of capabilities
199for the operations it supports. Below is an example of the capabilities for a
200PMD which supports the authentication algorithm SHA1_HMAC and the cipher
201algorithm AES_CBC.
202
203.. code-block:: c
204
205    static const struct rte_cryptodev_capabilities pmd_capabilities[] = {
206        {    /* SHA1 HMAC */
207            .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
208            .sym = {
209                .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
210                .auth = {
211                    .algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
212                    .block_size = 64,
213                    .key_size = {
214                        .min = 64,
215                        .max = 64,
216                        .increment = 0
217                    },
218                    .digest_size = {
219                        .min = 12,
220                        .max = 12,
221                        .increment = 0
222                    },
223                    .aad_size = { 0 },
224                    .iv_size = { 0 }
225                }
226            }
227        },
228        {    /* AES CBC */
229            .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
230            .sym = {
231                .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
232                .cipher = {
233                    .algo = RTE_CRYPTO_CIPHER_AES_CBC,
234                    .block_size = 16,
235                    .key_size = {
236                        .min = 16,
237                        .max = 32,
238                        .increment = 8
239                    },
240                    .iv_size = {
241                        .min = 16,
242                        .max = 16,
243                        .increment = 0
244                    }
245                }
246            }
247        }
248    }
249
250
251Capabilities Discovery
252~~~~~~~~~~~~~~~~~~~~~~
253
254Discovering the features and capabilities of a Crypto device poll mode driver
255is achieved through the ``rte_cryptodev_info_get`` function.
256
257.. code-block:: c
258
259   void rte_cryptodev_info_get(uint8_t dev_id,
260                               struct rte_cryptodev_info *dev_info);
261
262This allows the user to query a specific Crypto PMD and get all the device
263features and capabilities. The ``rte_cryptodev_info`` structure contains all the
264relevant information for the device.
265
266.. code-block:: c
267
268    struct rte_cryptodev_info {
269        const char *driver_name;
270        uint8_t driver_id;
271        struct rte_device *device;
272
273        uint64_t feature_flags;
274
275        const struct rte_cryptodev_capabilities *capabilities;
276
277        unsigned max_nb_queue_pairs;
278
279        struct {
280            unsigned max_nb_sessions;
281        } sym;
282    };
283
284
285Operation Processing
286--------------------
287
288Scheduling of Crypto operations on DPDK's application data path is
289performed using a burst oriented asynchronous API set. A queue pair on a Crypto
290device accepts a burst of Crypto operations using enqueue burst API. On physical
291Crypto devices the enqueue burst API will place the operations to be processed
292on the devices hardware input queue, for virtual devices the processing of the
293Crypto operations is usually completed during the enqueue call to the Crypto
294device. The dequeue burst API will retrieve any processed operations available
295from the queue pair on the Crypto device, from physical devices this is usually
296directly from the devices processed queue, and for virtual device's from a
297``rte_ring`` where processed operations are place after being processed on the
298enqueue call.
299
300
301Private data
302~~~~~~~~~~~~
303For session-based operations, the set and get API provides a mechanism for an
304application to store and retrieve the private data information stored along with
305the crypto session.
306
307For example, suppose an application is submitting a crypto operation with a session
308associated and wants to indicate private data information which is required to be
309used after completion of the crypto operation. In this case, the application can use
310the set API to set the private data and retrieve it using get API.
311
312.. code-block:: c
313
314	int rte_cryptodev_sym_session_set_private_data(
315		struct rte_cryptodev_sym_session *sess,	void *data, uint16_t size);
316
317	void * rte_cryptodev_sym_session_get_private_data(
318		struct rte_cryptodev_sym_session *sess);
319
320
321For session-less mode, the private data information can be placed along with the
322``struct rte_crypto_op``. The ``rte_crypto_op::private_data_offset`` indicates the
323start of private data information. The offset is counted from the start of the
324rte_crypto_op including other crypto information such as the IVs (since there can
325be an IV also for authentication).
326
327
328Enqueue / Dequeue Burst APIs
329~~~~~~~~~~~~~~~~~~~~~~~~~~~~
330
331The burst enqueue API uses a Crypto device identifier and a queue pair
332identifier to specify the Crypto device queue pair to schedule the processing on.
333The ``nb_ops`` parameter is the number of operations to process which are
334supplied in the ``ops`` array of ``rte_crypto_op`` structures.
335The enqueue function returns the number of operations it actually enqueued for
336processing, a return value equal to ``nb_ops`` means that all packets have been
337enqueued.
338
339.. code-block:: c
340
341   uint16_t rte_cryptodev_enqueue_burst(uint8_t dev_id, uint16_t qp_id,
342                                        struct rte_crypto_op **ops, uint16_t nb_ops)
343
344The dequeue API uses the same format as the enqueue API of processed but
345the ``nb_ops`` and ``ops`` parameters are now used to specify the max processed
346operations the user wishes to retrieve and the location in which to store them.
347The API call returns the actual number of processed operations returned, this
348can never be larger than ``nb_ops``.
349
350.. code-block:: c
351
352   uint16_t rte_cryptodev_dequeue_burst(uint8_t dev_id, uint16_t qp_id,
353                                        struct rte_crypto_op **ops, uint16_t nb_ops)
354
355
356Operation Representation
357~~~~~~~~~~~~~~~~~~~~~~~~
358
359An Crypto operation is represented by an rte_crypto_op structure, which is a
360generic metadata container for all necessary information required for the
361Crypto operation to be processed on a particular Crypto device poll mode driver.
362
363.. figure:: img/crypto_op.*
364
365The operation structure includes the operation type, the operation status
366and the session type (session-based/less), a reference to the operation
367specific data, which can vary in size and content depending on the operation
368being provisioned. It also contains the source mempool for the operation,
369if it allocated from a mempool.
370
371If Crypto operations are allocated from a Crypto operation mempool, see next
372section, there is also the ability to allocate private memory with the
373operation for applications purposes.
374
375Application software is responsible for specifying all the operation specific
376fields in the ``rte_crypto_op`` structure which are then used by the Crypto PMD
377to process the requested operation.
378
379
380Operation Management and Allocation
381~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
382
383The cryptodev library provides an API set for managing Crypto operations which
384utilize the Mempool Library to allocate operation buffers. Therefore, it ensures
385that the crytpo operation is interleaved optimally across the channels and
386ranks for optimal processing.
387A ``rte_crypto_op`` contains a field indicating the pool that it originated from.
388When calling ``rte_crypto_op_free(op)``, the operation returns to its original pool.
389
390.. code-block:: c
391
392   extern struct rte_mempool *
393   rte_crypto_op_pool_create(const char *name, enum rte_crypto_op_type type,
394                             unsigned nb_elts, unsigned cache_size, uint16_t priv_size,
395                             int socket_id);
396
397During pool creation ``rte_crypto_op_init()`` is called as a constructor to
398initialize each Crypto operation which subsequently calls
399``__rte_crypto_op_reset()`` to configure any operation type specific fields based
400on the type parameter.
401
402
403``rte_crypto_op_alloc()`` and ``rte_crypto_op_bulk_alloc()`` are used to allocate
404Crypto operations of a specific type from a given Crypto operation mempool.
405``__rte_crypto_op_reset()`` is called on each operation before being returned to
406allocate to a user so the operation is always in a good known state before use
407by the application.
408
409.. code-block:: c
410
411   struct rte_crypto_op *rte_crypto_op_alloc(struct rte_mempool *mempool,
412                                             enum rte_crypto_op_type type)
413
414   unsigned rte_crypto_op_bulk_alloc(struct rte_mempool *mempool,
415                                     enum rte_crypto_op_type type,
416                                     struct rte_crypto_op **ops, uint16_t nb_ops)
417
418``rte_crypto_op_free()`` is called by the application to return an operation to
419its allocating pool.
420
421.. code-block:: c
422
423   void rte_crypto_op_free(struct rte_crypto_op *op)
424
425
426Symmetric Cryptography Support
427------------------------------
428
429The cryptodev library currently provides support for the following symmetric
430Crypto operations; cipher, authentication, including chaining of these
431operations, as well as also supporting AEAD operations.
432
433
434Session and Session Management
435~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
436
437Sessions are used in symmetric cryptographic processing to store the immutable
438data defined in a cryptographic transform which is used in the operation
439processing of a packet flow. Sessions are used to manage information such as
440expand cipher keys and HMAC IPADs and OPADs, which need to be calculated for a
441particular Crypto operation, but are immutable on a packet to packet basis for
442a flow. Crypto sessions cache this immutable data in a optimal way for the
443underlying PMD and this allows further acceleration of the offload of
444Crypto workloads.
445
446.. figure:: img/cryptodev_sym_sess.*
447
448The Crypto device framework provides APIs to allocate and initizalize sessions
449for crypto devices, where sessions are mempool objects.
450It is the application's responsibility to create and manage the session mempools.
451This approach allows for different scenarios such as having a single session
452mempool for all crypto devices (where the mempool object size is big
453enough to hold the private session of any crypto device), as well as having
454multiple session mempools of different sizes for better memory usage.
455
456An application can use ``rte_cryptodev_sym_get_private_session_size()`` to
457get the private session size of given crypto device. This function would allow
458an application to calculate the max device session size of all crypto devices
459to create a single session mempool.
460If instead an application creates multiple session mempools, the Crypto device
461framework also provides ``rte_cryptodev_sym_get_header_session_size`` to get
462the size of an uninitialized session.
463
464Once the session mempools have been created, ``rte_cryptodev_sym_session_create()``
465is used to allocate an uninitialized session from the given mempool.
466The session then must be initialized using ``rte_cryptodev_sym_session_init()``
467for each of the required crypto devices. A symmetric transform chain
468is used to specify the operation and its parameters. See the section below for
469details on transforms.
470
471When a session is no longer used, user must call ``rte_cryptodev_sym_session_clear()``
472for each of the crypto devices that are using the session, to free all driver
473private session data. Once this is done, session should be freed using
474``rte_cryptodev_sym_session_free`` which returns them to their mempool.
475
476
477Transforms and Transform Chaining
478~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
479
480Symmetric Crypto transforms (``rte_crypto_sym_xform``) are the mechanism used
481to specify the details of the Crypto operation. For chaining of symmetric
482operations such as cipher encrypt and authentication generate, the next pointer
483allows transform to be chained together. Crypto devices which support chaining
484must publish the chaining of symmetric Crypto operations feature flag.
485
486Currently there are three transforms types cipher, authentication and AEAD.
487Also it is important to note that the order in which the
488transforms are passed indicates the order of the chaining.
489
490.. code-block:: c
491
492    struct rte_crypto_sym_xform {
493        struct rte_crypto_sym_xform *next;
494        /**< next xform in chain */
495        enum rte_crypto_sym_xform_type type;
496        /**< xform type */
497        union {
498            struct rte_crypto_auth_xform auth;
499            /**< Authentication / hash xform */
500            struct rte_crypto_cipher_xform cipher;
501            /**< Cipher xform */
502            struct rte_crypto_aead_xform aead;
503            /**< AEAD xform */
504        };
505    };
506
507The API does not place a limit on the number of transforms that can be chained
508together but this will be limited by the underlying Crypto device poll mode
509driver which is processing the operation.
510
511.. figure:: img/crypto_xform_chain.*
512
513
514Symmetric Operations
515~~~~~~~~~~~~~~~~~~~~
516
517The symmetric Crypto operation structure contains all the mutable data relating
518to performing symmetric cryptographic processing on a referenced mbuf data
519buffer. It is used for either cipher, authentication, AEAD and chained
520operations.
521
522As a minimum the symmetric operation must have a source data buffer (``m_src``),
523a valid session (or transform chain if in session-less mode) and the minimum
524authentication/ cipher/ AEAD parameters required depending on the type of operation
525specified in the session or the transform
526chain.
527
528.. code-block:: c
529
530    struct rte_crypto_sym_op {
531        struct rte_mbuf *m_src;
532        struct rte_mbuf *m_dst;
533
534        union {
535            struct rte_cryptodev_sym_session *session;
536            /**< Handle for the initialised session context */
537            struct rte_crypto_sym_xform *xform;
538            /**< Session-less API Crypto operation parameters */
539        };
540
541        union {
542            struct {
543                struct {
544                    uint32_t offset;
545                    uint32_t length;
546                } data; /**< Data offsets and length for AEAD */
547
548                struct {
549                    uint8_t *data;
550                    rte_iova_t phys_addr;
551                } digest; /**< Digest parameters */
552
553                struct {
554                    uint8_t *data;
555                    rte_iova_t phys_addr;
556                } aad;
557                /**< Additional authentication parameters */
558            } aead;
559
560            struct {
561                struct {
562                    struct {
563                        uint32_t offset;
564                        uint32_t length;
565                    } data; /**< Data offsets and length for ciphering */
566                } cipher;
567
568                struct {
569                    struct {
570                        uint32_t offset;
571                        uint32_t length;
572                    } data;
573                    /**< Data offsets and length for authentication */
574
575                    struct {
576                        uint8_t *data;
577                        rte_iova_t phys_addr;
578                    } digest; /**< Digest parameters */
579                } auth;
580            };
581        };
582    };
583
584Sample code
585-----------
586
587There are various sample applications that show how to use the cryptodev library,
588such as the L2fwd with Crypto sample application (L2fwd-crypto) and
589the IPSec Security Gateway application (ipsec-secgw).
590
591While these applications demonstrate how an application can be created to perform
592generic crypto operation, the required complexity hides the basic steps of
593how to use the cryptodev APIs.
594
595The following sample code shows the basic steps to encrypt several buffers
596with AES-CBC (although performing other crypto operations is similar),
597using one of the crypto PMDs available in DPDK.
598
599.. code-block:: c
600
601    /*
602     * Simple example to encrypt several buffers with AES-CBC using
603     * the Cryptodev APIs.
604     */
605
606    #define MAX_SESSIONS         1024
607    #define NUM_MBUFS            1024
608    #define POOL_CACHE_SIZE      128
609    #define BURST_SIZE           32
610    #define BUFFER_SIZE          1024
611    #define AES_CBC_IV_LENGTH    16
612    #define AES_CBC_KEY_LENGTH   16
613    #define IV_OFFSET            (sizeof(struct rte_crypto_op) + \
614                                 sizeof(struct rte_crypto_sym_op))
615
616    struct rte_mempool *mbuf_pool, *crypto_op_pool, *session_pool;
617    unsigned int session_size;
618    int ret;
619
620    /* Initialize EAL. */
621    ret = rte_eal_init(argc, argv);
622    if (ret < 0)
623        rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
624
625    uint8_t socket_id = rte_socket_id();
626
627    /* Create the mbuf pool. */
628    mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool",
629                                    NUM_MBUFS,
630                                    POOL_CACHE_SIZE,
631                                    0,
632                                    RTE_MBUF_DEFAULT_BUF_SIZE,
633                                    socket_id);
634    if (mbuf_pool == NULL)
635        rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
636
637    /*
638     * The IV is always placed after the crypto operation,
639     * so some private data is required to be reserved.
640     */
641    unsigned int crypto_op_private_data = AES_CBC_IV_LENGTH;
642
643    /* Create crypto operation pool. */
644    crypto_op_pool = rte_crypto_op_pool_create("crypto_op_pool",
645                                            RTE_CRYPTO_OP_TYPE_SYMMETRIC,
646                                            NUM_MBUFS,
647                                            POOL_CACHE_SIZE,
648                                            crypto_op_private_data,
649                                            socket_id);
650    if (crypto_op_pool == NULL)
651        rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n");
652
653    /* Create the virtual crypto device. */
654    char args[128];
655    const char *crypto_name = "crypto_aesni_mb0";
656    snprintf(args, sizeof(args), "socket_id=%d", socket_id);
657    ret = rte_vdev_init(crypto_name, args);
658    if (ret != 0)
659        rte_exit(EXIT_FAILURE, "Cannot create virtual device");
660
661    uint8_t cdev_id = rte_cryptodev_get_dev_id(crypto_name);
662
663    /* Get private session data size. */
664    session_size = rte_cryptodev_sym_get_private_session_size(cdev_id);
665
666    /*
667     * Create session mempool, with two objects per session,
668     * one for the session header and another one for the
669     * private session data for the crypto device.
670     */
671    session_pool = rte_mempool_create("session_pool",
672                                    MAX_SESSIONS * 2,
673                                    session_size,
674                                    POOL_CACHE_SIZE,
675                                    0, NULL, NULL, NULL,
676                                    NULL, socket_id,
677                                    0);
678
679    /* Configure the crypto device. */
680    struct rte_cryptodev_config conf = {
681        .nb_queue_pairs = 1,
682        .socket_id = socket_id
683    };
684    struct rte_cryptodev_qp_conf qp_conf = {
685        .nb_descriptors = 2048
686    };
687
688    if (rte_cryptodev_configure(cdev_id, &conf) < 0)
689        rte_exit(EXIT_FAILURE, "Failed to configure cryptodev %u", cdev_id);
690
691    if (rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
692                            socket_id, session_pool) < 0)
693        rte_exit(EXIT_FAILURE, "Failed to setup queue pair\n");
694
695    if (rte_cryptodev_start(cdev_id) < 0)
696        rte_exit(EXIT_FAILURE, "Failed to start device\n");
697
698    /* Create the crypto transform. */
699    uint8_t cipher_key[16] = {0};
700    struct rte_crypto_sym_xform cipher_xform = {
701        .next = NULL,
702        .type = RTE_CRYPTO_SYM_XFORM_CIPHER,
703        .cipher = {
704            .op = RTE_CRYPTO_CIPHER_OP_ENCRYPT,
705            .algo = RTE_CRYPTO_CIPHER_AES_CBC,
706            .key = {
707                .data = cipher_key,
708                .length = AES_CBC_KEY_LENGTH
709            },
710            .iv = {
711                .offset = IV_OFFSET,
712                .length = AES_CBC_IV_LENGTH
713            }
714        }
715    };
716
717    /* Create crypto session and initialize it for the crypto device. */
718    struct rte_cryptodev_sym_session *session;
719    session = rte_cryptodev_sym_session_create(session_pool);
720    if (session == NULL)
721        rte_exit(EXIT_FAILURE, "Session could not be created\n");
722
723    if (rte_cryptodev_sym_session_init(cdev_id, session,
724                    &cipher_xform, session_pool) < 0)
725        rte_exit(EXIT_FAILURE, "Session could not be initialized "
726                    "for the crypto device\n");
727
728    /* Get a burst of crypto operations. */
729    struct rte_crypto_op *crypto_ops[BURST_SIZE];
730    if (rte_crypto_op_bulk_alloc(crypto_op_pool,
731                            RTE_CRYPTO_OP_TYPE_SYMMETRIC,
732                            crypto_ops, BURST_SIZE) == 0)
733        rte_exit(EXIT_FAILURE, "Not enough crypto operations available\n");
734
735    /* Get a burst of mbufs. */
736    struct rte_mbuf *mbufs[BURST_SIZE];
737    if (rte_pktmbuf_alloc_bulk(mbuf_pool, mbufs, BURST_SIZE) < 0)
738        rte_exit(EXIT_FAILURE, "Not enough mbufs available");
739
740    /* Initialize the mbufs and append them to the crypto operations. */
741    unsigned int i;
742    for (i = 0; i < BURST_SIZE; i++) {
743        if (rte_pktmbuf_append(mbufs[i], BUFFER_SIZE) == NULL)
744            rte_exit(EXIT_FAILURE, "Not enough room in the mbuf\n");
745        crypto_ops[i]->sym->m_src = mbufs[i];
746    }
747
748    /* Set up the crypto operations. */
749    for (i = 0; i < BURST_SIZE; i++) {
750        struct rte_crypto_op *op = crypto_ops[i];
751        /* Modify bytes of the IV at the end of the crypto operation */
752        uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op, uint8_t *,
753                                                IV_OFFSET);
754
755        generate_random_bytes(iv_ptr, AES_CBC_IV_LENGTH);
756
757        op->sym->cipher.data.offset = 0;
758        op->sym->cipher.data.length = BUFFER_SIZE;
759
760        /* Attach the crypto session to the operation */
761        rte_crypto_op_attach_sym_session(op, session);
762    }
763
764    /* Enqueue the crypto operations in the crypto device. */
765    uint16_t num_enqueued_ops = rte_cryptodev_enqueue_burst(cdev_id, 0,
766                                            crypto_ops, BURST_SIZE);
767
768    /*
769     * Dequeue the crypto operations until all the operations
770     * are proccessed in the crypto device.
771     */
772    uint16_t num_dequeued_ops, total_num_dequeued_ops = 0;
773    do {
774        struct rte_crypto_op *dequeued_ops[BURST_SIZE];
775        num_dequeued_ops = rte_cryptodev_dequeue_burst(cdev_id, 0,
776                                        dequeued_ops, BURST_SIZE);
777        total_num_dequeued_ops += num_dequeued_ops;
778
779        /* Check if operation was processed successfully */
780        for (i = 0; i < num_dequeued_ops; i++) {
781            if (dequeued_ops[i]->status != RTE_CRYPTO_OP_STATUS_SUCCESS)
782                rte_exit(EXIT_FAILURE,
783                        "Some operations were not processed correctly");
784        }
785
786        rte_mempool_put_bulk(crypto_op_pool, (void **)dequeued_ops,
787                                            num_dequeued_ops);
788    } while (total_num_dequeued_ops < num_enqueued_ops);
789
790
791Asymmetric Cryptography
792-----------------------
793
794Asymmetric functionality is currently not supported by the cryptodev API.
795
796
797Crypto Device API
798~~~~~~~~~~~~~~~~~
799
800The cryptodev Library API is described in the *DPDK API Reference* document.
801