From 31850d26850e59cb20cdb84a8048d9f501f3cb22 Mon Sep 17 00:00:00 2001 From: Pablo de Lara Date: Fri, 28 Jul 2017 07:02:45 +0100 Subject: [PATCH] doc: add cryptodev sample code In order to illustrate in a simple way how to use the cryptodev API to perform a basic crypto operation, sample code has been added in the Programmer's Guide. Signed-off-by: Pablo de Lara Acked-by: John McNamara --- doc/guides/prog_guide/cryptodev_lib.rst | 206 ++++++++++++++++++++++++ 1 file changed, 206 insertions(+) diff --git a/doc/guides/prog_guide/cryptodev_lib.rst b/doc/guides/prog_guide/cryptodev_lib.rst index 81a6b1fa01..75ae085f66 100644 --- a/doc/guides/prog_guide/cryptodev_lib.rst +++ b/doc/guides/prog_guide/cryptodev_lib.rst @@ -573,6 +573,212 @@ chain. }; }; +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_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 ----------------------- -- 2.20.1