1.. BSD LICENSE 2 Copyright(c) 2016-2017 Intel Corporation. All rights reserved. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions 7 are met: 8 9 * Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in 13 the documentation and/or other materials provided with the 14 distribution. 15 * Neither the name of Intel Corporation nor the names of its 16 contributors may be used to endorse or promote products derived 17 from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31.. _l2_fwd_crypto_app: 32 33L2 Forwarding with Crypto Sample Application 34============================================ 35 36The L2 Forwarding with Crypto (l2fwd-crypto) sample application is a simple example of packet processing using 37the Data Plane Development Kit (DPDK), in conjunction with the Cryptodev library. 38 39Overview 40-------- 41 42The L2 Forwarding with Crypto sample application performs a crypto operation (cipher/hash) 43specified by the user from command line (or using the default values), 44with a crypto device capable of doing that operation, 45for each packet that is received on a RX_PORT and performs L2 forwarding. 46The destination port is the adjacent port from the enabled portmask, that is, 47if the first four ports are enabled (portmask 0xf), 48ports 0 and 1 forward into each other, and ports 2 and 3 forward into each other. 49Also, if MAC addresses updating is enabled, the MAC addresses are affected as follows: 50 51* The source MAC address is replaced by the TX_PORT MAC address 52 53* The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID 54 55Compiling the Application 56------------------------- 57 58To compile the sample application see :doc:`compiling`. 59 60The application is located in the ``l2fwd-crypt`` sub-directory. 61 62Running the Application 63----------------------- 64 65The application requires a number of command line options: 66 67.. code-block:: console 68 69 ./build/l2fwd-crypto [EAL options] -- [-p PORTMASK] [-q NQ] [-s] [-T PERIOD] / 70 [--cdev_type HW/SW/ANY] [--chain HASH_CIPHER/CIPHER_HASH/CIPHER_ONLY/HASH_ONLY/AEAD] / 71 [--cipher_algo ALGO] [--cipher_op ENCRYPT/DECRYPT] [--cipher_key KEY] / 72 [--cipher_key_random_size SIZE] [--cipher_iv IV] [--cipher_iv_random_size SIZE] / 73 [--auth_algo ALGO] [--auth_op GENERATE/VERIFY] [--auth_key KEY] / 74 [--auth_key_random_size SIZE] [--auth_iv IV] [--auth_iv_random_size SIZE] / 75 [--aead_algo ALGO] [--aead_op ENCRYPT/DECRYPT] [--aead_key KEY] / 76 [--aead_key_random_size SIZE] [--aead_iv] [--aead_iv_random_size SIZE] / 77 [--aad AAD] [--aad_random_size SIZE] / 78 [--digest size SIZE] [--sessionless] [--cryptodev_mask MASK] / 79 [--mac-updating] [--no-mac-updating] 80 81where, 82 83* p PORTMASK: A hexadecimal bitmask of the ports to configure (default is all the ports) 84 85* q NQ: A number of queues (=ports) per lcore (default is 1) 86 87* s: manage all ports from single core 88 89* T PERIOD: statistics will be refreshed each PERIOD seconds 90 91 (0 to disable, 10 default, 86400 maximum) 92 93* cdev_type: select preferred crypto device type: HW, SW or anything (ANY) 94 95 (default is ANY) 96 97* chain: select the operation chaining to perform: Cipher->Hash (CIPHER_HASH), 98 99 Hash->Cipher (HASH_CIPHER), Cipher (CIPHER_ONLY), Hash (HASH_ONLY) 100 101 or AEAD (AEAD) 102 103 (default is Cipher->Hash) 104 105* cipher_algo: select the ciphering algorithm (default is aes-cbc) 106 107* cipher_op: select the ciphering operation to perform: ENCRYPT or DECRYPT 108 109 (default is ENCRYPT) 110 111* cipher_key: set the ciphering key to be used. Bytes has to be separated with ":" 112 113* cipher_key_random_size: set the size of the ciphering key, 114 115 which will be generated randomly. 116 117 Note that if --cipher_key is used, this will be ignored. 118 119* cipher_iv: set the cipher IV to be used. Bytes has to be separated with ":" 120 121* cipher_iv_random_size: set the size of the cipher IV, which will be generated randomly. 122 123 Note that if --cipher_iv is used, this will be ignored. 124 125* auth_algo: select the authentication algorithm (default is sha1-hmac) 126 127* auth_op: select the authentication operation to perform: GENERATE or VERIFY 128 129 (default is GENERATE) 130 131* auth_key: set the authentication key to be used. Bytes has to be separated with ":" 132 133* auth_key_random_size: set the size of the authentication key, 134 135 which will be generated randomly. 136 137 Note that if --auth_key is used, this will be ignored. 138 139* auth_iv: set the auth IV to be used. Bytes has to be separated with ":" 140 141* auth_iv_random_size: set the size of the auth IV, which will be generated randomly. 142 143 Note that if --auth_iv is used, this will be ignored. 144 145* aead_algo: select the AEAD algorithm (default is aes-gcm) 146 147* aead_op: select the AEAD operation to perform: ENCRYPT or DECRYPT 148 149 (default is ENCRYPT) 150 151* aead_key: set the AEAD key to be used. Bytes has to be separated with ":" 152 153* aead_key_random_size: set the size of the AEAD key, 154 155 which will be generated randomly. 156 157 Note that if --aead_key is used, this will be ignored. 158 159* aead_iv: set the AEAD IV to be used. Bytes has to be separated with ":" 160 161* aead_iv_random_size: set the size of the AEAD IV, which will be generated randomly. 162 163 Note that if --aead_iv is used, this will be ignored. 164 165* aad: set the AAD to be used. Bytes has to be separated with ":" 166 167* aad_random_size: set the size of the AAD, which will be generated randomly. 168 169 Note that if --aad is used, this will be ignored. 170 171* digest_size: set the size of the digest to be generated/verified. 172 173* sessionless: no crypto session will be created. 174 175* cryptodev_mask: A hexadecimal bitmask of the cryptodevs to be used by the 176 application. 177 178 (default is all cryptodevs). 179 180* [no-]mac-updating: Enable or disable MAC addresses updating (enabled by default). 181 182 183The application requires that crypto devices capable of performing 184the specified crypto operation are available on application initialization. 185This means that HW crypto device/s must be bound to a DPDK driver or 186a SW crypto device/s (virtual crypto PMD) must be created (using --vdev). 187 188To run the application in linuxapp environment with 2 lcores, 2 ports and 2 crypto devices, issue the command: 189 190.. code-block:: console 191 192 $ ./build/l2fwd-crypto -l 0-1 -n 4 --vdev "crypto_aesni_mb0" \ 193 --vdev "crypto_aesni_mb1" -- -p 0x3 --chain CIPHER_HASH \ 194 --cipher_op ENCRYPT --cipher_algo aes-cbc \ 195 --cipher_key 00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f \ 196 --auth_op GENERATE --auth_algo aes-xcbc-mac \ 197 --auth_key 10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f 198 199Refer to the *DPDK Getting Started Guide* for general information on running applications 200and the Environment Abstraction Layer (EAL) options. 201 202Explanation 203----------- 204 205The L2 forward with Crypto application demonstrates the performance of a crypto operation 206on a packet received on a RX PORT before forwarding it to a TX PORT. 207 208The following figure illustrates a sample flow of a packet in the application, 209from reception until transmission. 210 211.. _figure_l2_fwd_encrypt_flow: 212 213.. figure:: img/l2_fwd_encrypt_flow.* 214 215 Encryption flow Through the L2 Forwarding with Crypto Application 216 217 218The following sections provide some explanation of the application. 219 220Crypto operation specification 221~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 222 223All the packets received in all the ports get transformed by the crypto device/s 224(ciphering and/or authentication). 225The crypto operation to be performed on the packet is parsed from the command line 226(go to "Running the Application section for all the options). 227 228If no parameter is passed, the default crypto operation is: 229 230* Encryption with AES-CBC with 128 bit key. 231 232* Authentication with SHA1-HMAC (generation). 233 234* Keys, IV and AAD are generated randomly. 235 236There are two methods to pass keys, IV and ADD from the command line: 237 238* Passing the full key, separated bytes by ":":: 239 240 --cipher_key 00:11:22:33:44 241 242* Passing the size, so key is generated randomly:: 243 244 --cipher_key_random_size 16 245 246**Note**: 247 If full key is passed (first method) and the size is passed as well (second method), 248 the latter will be ignored. 249 250Size of these keys are checked (regardless the method), before starting the app, 251to make sure that it is supported by the crypto devices. 252 253Crypto device initialization 254~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 255 256Once the encryption operation is defined, crypto devices are initialized. 257The crypto devices must be either bound to a DPDK driver (if they are physical devices) 258or created using the EAL option --vdev (if they are virtual devices), 259when running the application. 260 261The initialize_cryptodevs() function performs the device initialization. 262It iterates through the list of the available crypto devices and 263check which ones are capable of performing the operation. 264Each device has a set of capabilities associated with it, 265which are stored in the device info structure, so the function checks if the operation 266is within the structure of each device. 267 268The following code checks if the device supports the specified cipher algorithm 269(similar for the authentication algorithm): 270 271.. code-block:: c 272 273 /* Check if device supports cipher algo */ 274 i = 0; 275 opt_cipher_algo = options->cipher_xform.cipher.algo; 276 cap = &dev_info.capabilities[i]; 277 while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) { 278 cap_cipher_algo = cap->sym.cipher.algo; 279 if (cap->sym.xform_type == 280 RTE_CRYPTO_SYM_XFORM_CIPHER) { 281 if (cap_cipher_algo == opt_cipher_algo) { 282 if (check_type(options, &dev_info) == 0) 283 break; 284 } 285 } 286 cap = &dev_info.capabilities[++i]; 287 } 288 289If a capable crypto device is found, key sizes are checked to see if they are supported 290(cipher key and IV for the ciphering): 291 292.. code-block:: c 293 294 /* 295 * Check if length of provided cipher key is supported 296 * by the algorithm chosen. 297 */ 298 if (options->ckey_param) { 299 if (check_supported_size( 300 options->cipher_xform.cipher.key.length, 301 cap->sym.cipher.key_size.min, 302 cap->sym.cipher.key_size.max, 303 cap->sym.cipher.key_size.increment) 304 != 0) { 305 printf("Unsupported cipher key length\n"); 306 return -1; 307 } 308 /* 309 * Check if length of the cipher key to be randomly generated 310 * is supported by the algorithm chosen. 311 */ 312 } else if (options->ckey_random_size != -1) { 313 if (check_supported_size(options->ckey_random_size, 314 cap->sym.cipher.key_size.min, 315 cap->sym.cipher.key_size.max, 316 cap->sym.cipher.key_size.increment) 317 != 0) { 318 printf("Unsupported cipher key length\n"); 319 return -1; 320 } 321 options->cipher_xform.cipher.key.length = 322 options->ckey_random_size; 323 /* No size provided, use minimum size. */ 324 } else 325 options->cipher_xform.cipher.key.length = 326 cap->sym.cipher.key_size.min; 327 328After all the checks, the device is configured and it is added to the 329crypto device list. 330 331**Note**: 332 The number of crypto devices that supports the specified crypto operation 333 must be at least the number of ports to be used. 334 335Session creation 336~~~~~~~~~~~~~~~~ 337 338The crypto operation has a crypto session associated to it, which contains 339information such as the transform chain to perform (e.g. ciphering then hashing), 340pointers to the keys, lengths... etc. 341 342This session is created and is later attached to the crypto operation: 343 344.. code-block:: c 345 346 static struct rte_cryptodev_sym_session * 347 initialize_crypto_session(struct l2fwd_crypto_options *options, 348 uint8_t cdev_id) 349 { 350 struct rte_crypto_sym_xform *first_xform; 351 struct rte_cryptodev_sym_session *session; 352 uint8_t socket_id = rte_cryptodev_socket_id(cdev_id); 353 struct rte_mempool *sess_mp = session_pool_socket[socket_id]; 354 355 356 if (options->xform_chain == L2FWD_CRYPTO_AEAD) { 357 first_xform = &options->aead_xform; 358 } else if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH) { 359 first_xform = &options->cipher_xform; 360 first_xform->next = &options->auth_xform; 361 } else if (options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER) { 362 first_xform = &options->auth_xform; 363 first_xform->next = &options->cipher_xform; 364 } else if (options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) { 365 first_xform = &options->cipher_xform; 366 } else { 367 first_xform = &options->auth_xform; 368 } 369 370 session = rte_cryptodev_sym_session_create(sess_mp); 371 372 if (session == NULL) 373 return NULL; 374 375 if (rte_cryptodev_sym_session_init(cdev_id, session, 376 first_xform, sess_mp) < 0) 377 return NULL; 378 379 return session; 380 } 381 382 ... 383 384 port_cparams[i].session = initialize_crypto_session(options, 385 port_cparams[i].dev_id); 386 387Crypto operation creation 388~~~~~~~~~~~~~~~~~~~~~~~~~ 389 390Given N packets received from a RX PORT, N crypto operations are allocated 391and filled: 392 393.. code-block:: c 394 395 if (nb_rx) { 396 /* 397 * If we can't allocate a crypto_ops, then drop 398 * the rest of the burst and dequeue and 399 * process the packets to free offload structs 400 */ 401 if (rte_crypto_op_bulk_alloc( 402 l2fwd_crypto_op_pool, 403 RTE_CRYPTO_OP_TYPE_SYMMETRIC, 404 ops_burst, nb_rx) != 405 nb_rx) { 406 for (j = 0; j < nb_rx; j++) 407 rte_pktmbuf_free(pkts_burst[i]); 408 409 nb_rx = 0; 410 } 411 412After filling the crypto operation (including session attachment), 413the mbuf which will be transformed is attached to it:: 414 415 op->sym->m_src = m; 416 417Since no destination mbuf is set, the source mbuf will be overwritten 418after the operation is done (in-place). 419 420Crypto operation enqueuing/dequeuing 421~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 422 423Once the operation has been created, it has to be enqueued in one of the crypto devices. 424Before doing so, for performance reasons, the operation stays in a buffer. 425When the buffer has enough operations (MAX_PKT_BURST), they are enqueued in the device, 426which will perform the operation at that moment: 427 428.. code-block:: c 429 430 static int 431 l2fwd_crypto_enqueue(struct rte_crypto_op *op, 432 struct l2fwd_crypto_params *cparams) 433 { 434 unsigned lcore_id, len; 435 struct lcore_queue_conf *qconf; 436 437 lcore_id = rte_lcore_id(); 438 439 qconf = &lcore_queue_conf[lcore_id]; 440 len = qconf->op_buf[cparams->dev_id].len; 441 qconf->op_buf[cparams->dev_id].buffer[len] = op; 442 len++; 443 444 /* enough ops to be sent */ 445 if (len == MAX_PKT_BURST) { 446 l2fwd_crypto_send_burst(qconf, MAX_PKT_BURST, cparams); 447 len = 0; 448 } 449 450 qconf->op_buf[cparams->dev_id].len = len; 451 return 0; 452 } 453 454 ... 455 456 static int 457 l2fwd_crypto_send_burst(struct lcore_queue_conf *qconf, unsigned n, 458 struct l2fwd_crypto_params *cparams) 459 { 460 struct rte_crypto_op **op_buffer; 461 unsigned ret; 462 463 op_buffer = (struct rte_crypto_op **) 464 qconf->op_buf[cparams->dev_id].buffer; 465 466 ret = rte_cryptodev_enqueue_burst(cparams->dev_id, 467 cparams->qp_id, op_buffer, (uint16_t) n); 468 469 crypto_statistics[cparams->dev_id].enqueued += ret; 470 if (unlikely(ret < n)) { 471 crypto_statistics[cparams->dev_id].errors += (n - ret); 472 do { 473 rte_pktmbuf_free(op_buffer[ret]->sym->m_src); 474 rte_crypto_op_free(op_buffer[ret]); 475 } while (++ret < n); 476 } 477 478 return 0; 479 } 480 481After this, the operations are dequeued from the device, and the transformed mbuf 482is extracted from the operation. Then, the operation is freed and the mbuf is 483forwarded as it is done in the L2 forwarding application. 484 485.. code-block:: c 486 487 /* Dequeue packets from Crypto device */ 488 do { 489 nb_rx = rte_cryptodev_dequeue_burst( 490 cparams->dev_id, cparams->qp_id, 491 ops_burst, MAX_PKT_BURST); 492 493 crypto_statistics[cparams->dev_id].dequeued += 494 nb_rx; 495 496 /* Forward crypto'd packets */ 497 for (j = 0; j < nb_rx; j++) { 498 m = ops_burst[j]->sym->m_src; 499 500 rte_crypto_op_free(ops_burst[j]); 501 l2fwd_simple_forward(m, portid); 502 } 503 } while (nb_rx == MAX_PKT_BURST); 504