1 .. SPDX-License-Identifier: BSD-3-Clause
2 Copyright(c) 2016-2017 Intel Corporation.
6 L2 Forwarding with Crypto Sample Application
7 ============================================
9 The L2 Forwarding with Crypto (l2fwd-crypto) sample application is a simple example of packet processing using
10 the Data Plane Development Kit (DPDK), in conjunction with the Cryptodev library.
15 The L2 Forwarding with Crypto sample application performs a crypto operation (cipher/hash)
16 specified by the user from command line (or using the default values),
17 with a crypto device capable of doing that operation,
18 for each packet that is received on a RX_PORT and performs L2 forwarding.
19 The destination port is the adjacent port from the enabled portmask, that is,
20 if the first four ports are enabled (portmask 0xf),
21 ports 0 and 1 forward into each other, and ports 2 and 3 forward into each other.
22 Also, if MAC addresses updating is enabled, the MAC addresses are affected as follows:
24 * The source MAC address is replaced by the TX_PORT MAC address
26 * The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID
28 Compiling the Application
29 -------------------------
31 To compile the sample application see :doc:`compiling`.
33 The application is located in the ``l2fwd-crypt`` sub-directory.
35 Running the Application
36 -----------------------
38 The application requires a number of command line options:
40 .. code-block:: console
42 ./build/l2fwd-crypto [EAL options] -- [-p PORTMASK] [-q NQ] [-s] [-T PERIOD] /
43 [--cdev_type HW/SW/ANY] [--chain HASH_CIPHER/CIPHER_HASH/CIPHER_ONLY/HASH_ONLY/AEAD] /
44 [--cipher_algo ALGO] [--cipher_op ENCRYPT/DECRYPT] [--cipher_key KEY] /
45 [--cipher_key_random_size SIZE] [--cipher_iv IV] [--cipher_iv_random_size SIZE] /
46 [--auth_algo ALGO] [--auth_op GENERATE/VERIFY] [--auth_key KEY] /
47 [--auth_key_random_size SIZE] [--auth_iv IV] [--auth_iv_random_size SIZE] /
48 [--aead_algo ALGO] [--aead_op ENCRYPT/DECRYPT] [--aead_key KEY] /
49 [--aead_key_random_size SIZE] [--aead_iv] [--aead_iv_random_size SIZE] /
50 [--aad AAD] [--aad_random_size SIZE] /
51 [--digest size SIZE] [--sessionless] [--cryptodev_mask MASK] /
52 [--mac-updating] [--no-mac-updating]
56 * p PORTMASK: A hexadecimal bitmask of the ports to configure (default is all the ports)
58 * q NQ: A number of queues (=ports) per lcore (default is 1)
60 * s: manage all ports from single core
62 * T PERIOD: statistics will be refreshed each PERIOD seconds
64 (0 to disable, 10 default, 86400 maximum)
66 * cdev_type: select preferred crypto device type: HW, SW or anything (ANY)
70 * chain: select the operation chaining to perform: Cipher->Hash (CIPHER_HASH),
72 Hash->Cipher (HASH_CIPHER), Cipher (CIPHER_ONLY), Hash (HASH_ONLY)
76 (default is Cipher->Hash)
78 * cipher_algo: select the ciphering algorithm (default is aes-cbc)
80 * cipher_op: select the ciphering operation to perform: ENCRYPT or DECRYPT
84 * cipher_key: set the ciphering key to be used. Bytes has to be separated with ":"
86 * cipher_key_random_size: set the size of the ciphering key,
88 which will be generated randomly.
90 Note that if --cipher_key is used, this will be ignored.
92 * cipher_iv: set the cipher IV to be used. Bytes has to be separated with ":"
94 * cipher_iv_random_size: set the size of the cipher IV, which will be generated randomly.
96 Note that if --cipher_iv is used, this will be ignored.
98 * auth_algo: select the authentication algorithm (default is sha1-hmac)
100 * auth_op: select the authentication operation to perform: GENERATE or VERIFY
102 (default is GENERATE)
104 * auth_key: set the authentication key to be used. Bytes has to be separated with ":"
106 * auth_key_random_size: set the size of the authentication key,
108 which will be generated randomly.
110 Note that if --auth_key is used, this will be ignored.
112 * auth_iv: set the auth IV to be used. Bytes has to be separated with ":"
114 * auth_iv_random_size: set the size of the auth IV, which will be generated randomly.
116 Note that if --auth_iv is used, this will be ignored.
118 * aead_algo: select the AEAD algorithm (default is aes-gcm)
120 * aead_op: select the AEAD operation to perform: ENCRYPT or DECRYPT
124 * aead_key: set the AEAD key to be used. Bytes has to be separated with ":"
126 * aead_key_random_size: set the size of the AEAD key,
128 which will be generated randomly.
130 Note that if --aead_key is used, this will be ignored.
132 * aead_iv: set the AEAD IV to be used. Bytes has to be separated with ":"
134 * aead_iv_random_size: set the size of the AEAD IV, which will be generated randomly.
136 Note that if --aead_iv is used, this will be ignored.
138 * aad: set the AAD to be used. Bytes has to be separated with ":"
140 * aad_random_size: set the size of the AAD, which will be generated randomly.
142 Note that if --aad is used, this will be ignored.
144 * digest_size: set the size of the digest to be generated/verified.
146 * sessionless: no crypto session will be created.
148 * cryptodev_mask: A hexadecimal bitmask of the cryptodevs to be used by the
151 (default is all cryptodevs).
153 * [no-]mac-updating: Enable or disable MAC addresses updating (enabled by default).
156 The application requires that crypto devices capable of performing
157 the specified crypto operation are available on application initialization.
158 This means that HW crypto device/s must be bound to a DPDK driver or
159 a SW crypto device/s (virtual crypto PMD) must be created (using --vdev).
161 To run the application in linux environment with 2 lcores, 2 ports and 2 crypto devices, issue the command:
163 .. code-block:: console
165 $ ./build/l2fwd-crypto -l 0-1 -n 4 --vdev "crypto_aesni_mb0" \
166 --vdev "crypto_aesni_mb1" -- -p 0x3 --chain CIPHER_HASH \
167 --cipher_op ENCRYPT --cipher_algo aes-cbc \
168 --cipher_key 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f \
169 --auth_op GENERATE --auth_algo aes-xcbc-mac \
170 --auth_key 10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f
172 Refer to the *DPDK Getting Started Guide* for general information on running applications
173 and the Environment Abstraction Layer (EAL) options.
177 * The ``l2fwd-crypto`` sample application requires IPv4 packets for crypto operation.
179 * If multiple Ethernet ports is passed, then equal number of crypto devices are to be passed.
181 * All crypto devices shall use the same session.
186 The L2 forward with Crypto application demonstrates the performance of a crypto operation
187 on a packet received on a RX PORT before forwarding it to a TX PORT.
189 The following figure illustrates a sample flow of a packet in the application,
190 from reception until transmission.
192 .. _figure_l2_fwd_encrypt_flow:
194 .. figure:: img/l2_fwd_encrypt_flow.*
196 Encryption flow Through the L2 Forwarding with Crypto Application
199 The following sections provide some explanation of the application.
201 Crypto operation specification
202 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204 All the packets received in all the ports get transformed by the crypto device/s
205 (ciphering and/or authentication).
206 The crypto operation to be performed on the packet is parsed from the command line
207 (go to "Running the Application section for all the options).
209 If no parameter is passed, the default crypto operation is:
211 * Encryption with AES-CBC with 128 bit key.
213 * Authentication with SHA1-HMAC (generation).
215 * Keys, IV and AAD are generated randomly.
217 There are two methods to pass keys, IV and ADD from the command line:
219 * Passing the full key, separated bytes by ":"::
221 --cipher_key 00:11:22:33:44
223 * Passing the size, so key is generated randomly::
225 --cipher_key_random_size 16
228 If full key is passed (first method) and the size is passed as well (second method),
229 the latter will be ignored.
231 Size of these keys are checked (regardless the method), before starting the app,
232 to make sure that it is supported by the crypto devices.
234 Crypto device initialization
235 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237 Once the encryption operation is defined, crypto devices are initialized.
238 The crypto devices must be either bound to a DPDK driver (if they are physical devices)
239 or created using the EAL option --vdev (if they are virtual devices),
240 when running the application.
242 The initialize_cryptodevs() function performs the device initialization.
243 It iterates through the list of the available crypto devices and
244 check which ones are capable of performing the operation.
245 Each device has a set of capabilities associated with it,
246 which are stored in the device info structure, so the function checks if the operation
247 is within the structure of each device.
249 The following code checks if the device supports the specified cipher algorithm
250 (similar for the authentication algorithm):
254 /* Check if device supports cipher algo */
256 opt_cipher_algo = options->cipher_xform.cipher.algo;
257 cap = &dev_info.capabilities[i];
258 while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
259 cap_cipher_algo = cap->sym.cipher.algo;
260 if (cap->sym.xform_type ==
261 RTE_CRYPTO_SYM_XFORM_CIPHER) {
262 if (cap_cipher_algo == opt_cipher_algo) {
263 if (check_type(options, &dev_info) == 0)
267 cap = &dev_info.capabilities[++i];
270 If a capable crypto device is found, key sizes are checked to see if they are supported
271 (cipher key and IV for the ciphering):
276 * Check if length of provided cipher key is supported
277 * by the algorithm chosen.
279 if (options->ckey_param) {
280 if (check_supported_size(
281 options->cipher_xform.cipher.key.length,
282 cap->sym.cipher.key_size.min,
283 cap->sym.cipher.key_size.max,
284 cap->sym.cipher.key_size.increment)
286 printf("Unsupported cipher key length\n");
290 * Check if length of the cipher key to be randomly generated
291 * is supported by the algorithm chosen.
293 } else if (options->ckey_random_size != -1) {
294 if (check_supported_size(options->ckey_random_size,
295 cap->sym.cipher.key_size.min,
296 cap->sym.cipher.key_size.max,
297 cap->sym.cipher.key_size.increment)
299 printf("Unsupported cipher key length\n");
302 options->cipher_xform.cipher.key.length =
303 options->ckey_random_size;
304 /* No size provided, use minimum size. */
306 options->cipher_xform.cipher.key.length =
307 cap->sym.cipher.key_size.min;
309 After all the checks, the device is configured and it is added to the
313 The number of crypto devices that supports the specified crypto operation
314 must be at least the number of ports to be used.
319 The crypto operation has a crypto session associated to it, which contains
320 information such as the transform chain to perform (e.g. ciphering then hashing),
321 pointers to the keys, lengths... etc.
323 This session is created and is later attached to the crypto operation:
327 static struct rte_cryptodev_sym_session *
328 initialize_crypto_session(struct l2fwd_crypto_options *options,
331 struct rte_crypto_sym_xform *first_xform;
332 struct rte_cryptodev_sym_session *session;
333 uint8_t socket_id = rte_cryptodev_socket_id(cdev_id);
334 struct rte_mempool *sess_mp = session_pool_socket[socket_id];
337 if (options->xform_chain == L2FWD_CRYPTO_AEAD) {
338 first_xform = &options->aead_xform;
339 } else if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH) {
340 first_xform = &options->cipher_xform;
341 first_xform->next = &options->auth_xform;
342 } else if (options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER) {
343 first_xform = &options->auth_xform;
344 first_xform->next = &options->cipher_xform;
345 } else if (options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
346 first_xform = &options->cipher_xform;
348 first_xform = &options->auth_xform;
351 session = rte_cryptodev_sym_session_create(sess_mp);
356 if (rte_cryptodev_sym_session_init(cdev_id, session,
357 first_xform, sess_mp) < 0)
365 port_cparams[i].session = initialize_crypto_session(options,
366 port_cparams[i].dev_id);
368 Crypto operation creation
369 ~~~~~~~~~~~~~~~~~~~~~~~~~
371 Given N packets received from a RX PORT, N crypto operations are allocated
378 * If we can't allocate a crypto_ops, then drop
379 * the rest of the burst and dequeue and
380 * process the packets to free offload structs
382 if (rte_crypto_op_bulk_alloc(
383 l2fwd_crypto_op_pool,
384 RTE_CRYPTO_OP_TYPE_SYMMETRIC,
387 for (j = 0; j < nb_rx; j++)
388 rte_pktmbuf_free(pkts_burst[i]);
393 After filling the crypto operation (including session attachment),
394 the mbuf which will be transformed is attached to it::
398 Since no destination mbuf is set, the source mbuf will be overwritten
399 after the operation is done (in-place).
401 Crypto operation enqueuing/dequeuing
402 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
404 Once the operation has been created, it has to be enqueued in one of the crypto devices.
405 Before doing so, for performance reasons, the operation stays in a buffer.
406 When the buffer has enough operations (MAX_PKT_BURST), they are enqueued in the device,
407 which will perform the operation at that moment:
412 l2fwd_crypto_enqueue(struct rte_crypto_op *op,
413 struct l2fwd_crypto_params *cparams)
415 unsigned lcore_id, len;
416 struct lcore_queue_conf *qconf;
418 lcore_id = rte_lcore_id();
420 qconf = &lcore_queue_conf[lcore_id];
421 len = qconf->op_buf[cparams->dev_id].len;
422 qconf->op_buf[cparams->dev_id].buffer[len] = op;
425 /* enough ops to be sent */
426 if (len == MAX_PKT_BURST) {
427 l2fwd_crypto_send_burst(qconf, MAX_PKT_BURST, cparams);
431 qconf->op_buf[cparams->dev_id].len = len;
438 l2fwd_crypto_send_burst(struct lcore_queue_conf *qconf, unsigned n,
439 struct l2fwd_crypto_params *cparams)
441 struct rte_crypto_op **op_buffer;
444 op_buffer = (struct rte_crypto_op **)
445 qconf->op_buf[cparams->dev_id].buffer;
447 ret = rte_cryptodev_enqueue_burst(cparams->dev_id,
448 cparams->qp_id, op_buffer, (uint16_t) n);
450 crypto_statistics[cparams->dev_id].enqueued += ret;
451 if (unlikely(ret < n)) {
452 crypto_statistics[cparams->dev_id].errors += (n - ret);
454 rte_pktmbuf_free(op_buffer[ret]->sym->m_src);
455 rte_crypto_op_free(op_buffer[ret]);
462 After this, the operations are dequeued from the device, and the transformed mbuf
463 is extracted from the operation. Then, the operation is freed and the mbuf is
464 forwarded as it is done in the L2 forwarding application.
468 /* Dequeue packets from Crypto device */
470 nb_rx = rte_cryptodev_dequeue_burst(
471 cparams->dev_id, cparams->qp_id,
472 ops_burst, MAX_PKT_BURST);
474 crypto_statistics[cparams->dev_id].dequeued +=
477 /* Forward crypto'd packets */
478 for (j = 0; j < nb_rx; j++) {
479 m = ops_burst[j]->sym->m_src;
481 rte_crypto_op_free(ops_burst[j]);
482 l2fwd_simple_forward(m, portid);
484 } while (nb_rx == MAX_PKT_BURST);