1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2015-2016 Intel Corporation
3 */
4
5 #include <time.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdint.h>
10 #include <inttypes.h>
11 #include <sys/types.h>
12 #include <sys/queue.h>
13 #include <netinet/in.h>
14 #include <setjmp.h>
15 #include <stdarg.h>
16 #include <ctype.h>
17 #include <errno.h>
18 #include <getopt.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <signal.h>
22
23 #include <rte_string_fns.h>
24 #include <rte_branch_prediction.h>
25 #include <rte_common.h>
26 #include <rte_cryptodev.h>
27 #include <rte_cycles.h>
28 #include <rte_debug.h>
29 #include <rte_eal.h>
30 #include <rte_ether.h>
31 #include <rte_ethdev.h>
32 #include <rte_interrupts.h>
33 #include <rte_ip.h>
34 #include <rte_launch.h>
35 #include <rte_lcore.h>
36 #include <rte_log.h>
37 #include <rte_malloc.h>
38 #include <rte_mbuf.h>
39 #include <rte_memcpy.h>
40 #include <rte_memory.h>
41 #include <rte_mempool.h>
42 #include <rte_per_lcore.h>
43 #include <rte_prefetch.h>
44 #include <rte_random.h>
45 #include <rte_hexdump.h>
46 #ifdef RTE_CRYPTO_SCHEDULER
47 #include <rte_cryptodev_scheduler.h>
48 #endif
49
50 enum cdev_type {
51 CDEV_TYPE_ANY,
52 CDEV_TYPE_HW,
53 CDEV_TYPE_SW
54 };
55
56 #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
57
58 #define NB_MBUF 8192
59
60 #define MAX_STR_LEN 32
61 #define MAX_KEY_SIZE 128
62 #define MAX_IV_SIZE 16
63 #define MAX_AAD_SIZE 65535
64 #define MAX_PKT_BURST 32
65 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
66 #define SESSION_POOL_CACHE_SIZE 0
67
68 #define MAXIMUM_IV_LENGTH 16
69 #define IV_OFFSET (sizeof(struct rte_crypto_op) + \
70 sizeof(struct rte_crypto_sym_op))
71
72 /*
73 * Configurable number of RX/TX ring descriptors
74 */
75 #define RX_DESC_DEFAULT 1024
76 #define TX_DESC_DEFAULT 1024
77
78 static uint16_t nb_rxd = RX_DESC_DEFAULT;
79 static uint16_t nb_txd = TX_DESC_DEFAULT;
80
81 /* ethernet addresses of ports */
82 static struct rte_ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
83
84 /* mask of enabled ports */
85 static uint64_t l2fwd_enabled_port_mask;
86 static uint64_t l2fwd_enabled_crypto_mask;
87
88 /* list of enabled ports */
89 static uint16_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];
90
91
92 struct pkt_buffer {
93 unsigned len;
94 struct rte_mbuf *buffer[MAX_PKT_BURST];
95 };
96
97 struct op_buffer {
98 unsigned len;
99 struct rte_crypto_op *buffer[MAX_PKT_BURST];
100 };
101
102 #define MAX_RX_QUEUE_PER_LCORE 16
103 #define MAX_TX_QUEUE_PER_PORT 16
104
105 enum l2fwd_crypto_xform_chain {
106 L2FWD_CRYPTO_CIPHER_HASH,
107 L2FWD_CRYPTO_HASH_CIPHER,
108 L2FWD_CRYPTO_CIPHER_ONLY,
109 L2FWD_CRYPTO_HASH_ONLY,
110 L2FWD_CRYPTO_AEAD
111 };
112
113 struct l2fwd_key {
114 uint8_t *data;
115 uint32_t length;
116 rte_iova_t phys_addr;
117 };
118
119 struct l2fwd_iv {
120 uint8_t *data;
121 uint16_t length;
122 };
123
124 /** l2fwd crypto application command line options */
125 struct l2fwd_crypto_options {
126 unsigned portmask;
127 unsigned nb_ports_per_lcore;
128 unsigned refresh_period;
129 unsigned single_lcore:1;
130
131 enum cdev_type type;
132 unsigned sessionless:1;
133
134 enum l2fwd_crypto_xform_chain xform_chain;
135
136 struct rte_crypto_sym_xform cipher_xform;
137 unsigned ckey_param;
138 int ckey_random_size;
139 uint8_t cipher_key[MAX_KEY_SIZE];
140
141 struct l2fwd_iv cipher_iv;
142 unsigned int cipher_iv_param;
143 int cipher_iv_random_size;
144
145 struct rte_crypto_sym_xform auth_xform;
146 uint8_t akey_param;
147 int akey_random_size;
148 uint8_t auth_key[MAX_KEY_SIZE];
149
150 struct l2fwd_iv auth_iv;
151 unsigned int auth_iv_param;
152 int auth_iv_random_size;
153
154 struct rte_crypto_sym_xform aead_xform;
155 unsigned int aead_key_param;
156 int aead_key_random_size;
157 uint8_t aead_key[MAX_KEY_SIZE];
158
159 struct l2fwd_iv aead_iv;
160 unsigned int aead_iv_param;
161 int aead_iv_random_size;
162
163 struct l2fwd_key aad;
164 unsigned aad_param;
165 int aad_random_size;
166
167 int digest_size;
168
169 uint16_t block_size;
170 char string_type[MAX_STR_LEN];
171
172 uint64_t cryptodev_mask;
173
174 unsigned int mac_updating;
175 };
176
177 /** l2fwd crypto lcore params */
178 struct l2fwd_crypto_params {
179 uint8_t dev_id;
180 uint8_t qp_id;
181
182 unsigned digest_length;
183 unsigned block_size;
184
185 uint32_t cipher_dataunit_len;
186
187 struct l2fwd_iv cipher_iv;
188 struct l2fwd_iv auth_iv;
189 struct l2fwd_iv aead_iv;
190 struct l2fwd_key aad;
191 void *session;
192
193 uint8_t do_cipher;
194 uint8_t do_hash;
195 uint8_t do_aead;
196 uint8_t hash_verify;
197
198 enum rte_crypto_cipher_algorithm cipher_algo;
199 enum rte_crypto_auth_algorithm auth_algo;
200 enum rte_crypto_aead_algorithm aead_algo;
201 };
202
203 /** lcore configuration */
204 struct __rte_cache_aligned lcore_queue_conf {
205 unsigned nb_rx_ports;
206 uint16_t rx_port_list[MAX_RX_QUEUE_PER_LCORE];
207
208 unsigned nb_crypto_devs;
209 unsigned cryptodev_list[MAX_RX_QUEUE_PER_LCORE];
210
211 struct op_buffer op_buf[RTE_CRYPTO_MAX_DEVS];
212 struct pkt_buffer pkt_buf[RTE_MAX_ETHPORTS];
213 };
214
215 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
216
217 static struct rte_eth_conf port_conf = {
218 .rxmode = {
219 .mq_mode = RTE_ETH_MQ_RX_NONE,
220 },
221 .txmode = {
222 .mq_mode = RTE_ETH_MQ_TX_NONE,
223 },
224 };
225
226 struct rte_mempool *l2fwd_pktmbuf_pool;
227 struct rte_mempool *l2fwd_crypto_op_pool;
228 static struct {
229 struct rte_mempool *sess_mp;
230 } session_pool_socket[RTE_MAX_NUMA_NODES];
231
232 /* Per-port statistics struct */
233 struct __rte_cache_aligned l2fwd_port_statistics {
234 uint64_t tx;
235 uint64_t rx;
236
237 uint64_t crypto_enqueued;
238 uint64_t crypto_dequeued;
239
240 uint64_t dropped;
241 };
242
243 struct __rte_cache_aligned l2fwd_crypto_statistics {
244 uint64_t enqueued;
245 uint64_t dequeued;
246
247 uint64_t errors;
248 };
249
250 struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];
251 struct l2fwd_crypto_statistics crypto_statistics[RTE_CRYPTO_MAX_DEVS];
252
253 /* A tsc-based timer responsible for triggering statistics printout */
254 #define TIMER_MILLISECOND (rte_get_tsc_hz() / 1000)
255 #define MAX_TIMER_PERIOD 86400UL /* 1 day max */
256 #define DEFAULT_TIMER_PERIOD 10UL
257
258 /* Global signal */
259 static volatile bool signal_received;
260
261 /* Print out statistics on packets dropped */
262 static void
print_stats(void)263 print_stats(void)
264 {
265 uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;
266 uint64_t total_packets_enqueued, total_packets_dequeued,
267 total_packets_errors;
268 uint16_t portid;
269 uint64_t cdevid;
270
271 total_packets_dropped = 0;
272 total_packets_tx = 0;
273 total_packets_rx = 0;
274 total_packets_enqueued = 0;
275 total_packets_dequeued = 0;
276 total_packets_errors = 0;
277
278 const char clr[] = { 27, '[', '2', 'J', '\0' };
279 const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
280
281 /* Clear screen and move to top left */
282 printf("%s%s", clr, topLeft);
283
284 printf("\nPort statistics ====================================");
285
286 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
287 /* skip disabled ports */
288 if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
289 continue;
290 printf("\nStatistics for port %u ------------------------------"
291 "\nPackets sent: %32"PRIu64
292 "\nPackets received: %28"PRIu64
293 "\nPackets dropped: %29"PRIu64,
294 portid,
295 port_statistics[portid].tx,
296 port_statistics[portid].rx,
297 port_statistics[portid].dropped);
298
299 total_packets_dropped += port_statistics[portid].dropped;
300 total_packets_tx += port_statistics[portid].tx;
301 total_packets_rx += port_statistics[portid].rx;
302 }
303 printf("\nCrypto statistics ==================================");
304
305 for (cdevid = 0; cdevid < RTE_CRYPTO_MAX_DEVS; cdevid++) {
306 /* skip disabled ports */
307 if ((l2fwd_enabled_crypto_mask & (((uint64_t)1) << cdevid)) == 0)
308 continue;
309 printf("\nStatistics for cryptodev %"PRIu64
310 " -------------------------"
311 "\nPackets enqueued: %28"PRIu64
312 "\nPackets dequeued: %28"PRIu64
313 "\nPackets errors: %30"PRIu64,
314 cdevid,
315 crypto_statistics[cdevid].enqueued,
316 crypto_statistics[cdevid].dequeued,
317 crypto_statistics[cdevid].errors);
318
319 total_packets_enqueued += crypto_statistics[cdevid].enqueued;
320 total_packets_dequeued += crypto_statistics[cdevid].dequeued;
321 total_packets_errors += crypto_statistics[cdevid].errors;
322 }
323 printf("\nAggregate statistics ==============================="
324 "\nTotal packets received: %22"PRIu64
325 "\nTotal packets enqueued: %22"PRIu64
326 "\nTotal packets dequeued: %22"PRIu64
327 "\nTotal packets sent: %26"PRIu64
328 "\nTotal packets dropped: %23"PRIu64
329 "\nTotal packets crypto errors: %17"PRIu64,
330 total_packets_rx,
331 total_packets_enqueued,
332 total_packets_dequeued,
333 total_packets_tx,
334 total_packets_dropped,
335 total_packets_errors);
336 printf("\n====================================================\n");
337
338 fflush(stdout);
339 }
340
341 /* l2fwd_crypto_send_burst 8< */
342 static int
l2fwd_crypto_send_burst(struct lcore_queue_conf * qconf,unsigned n,struct l2fwd_crypto_params * cparams)343 l2fwd_crypto_send_burst(struct lcore_queue_conf *qconf, unsigned n,
344 struct l2fwd_crypto_params *cparams)
345 {
346 struct rte_crypto_op **op_buffer;
347 unsigned ret;
348
349 op_buffer = (struct rte_crypto_op **)
350 qconf->op_buf[cparams->dev_id].buffer;
351
352 ret = rte_cryptodev_enqueue_burst(cparams->dev_id,
353 cparams->qp_id, op_buffer, (uint16_t) n);
354
355 crypto_statistics[cparams->dev_id].enqueued += ret;
356 if (unlikely(ret < n)) {
357 crypto_statistics[cparams->dev_id].errors += (n - ret);
358 do {
359 rte_pktmbuf_free(op_buffer[ret]->sym->m_src);
360 rte_crypto_op_free(op_buffer[ret]);
361 } while (++ret < n);
362 }
363
364 return 0;
365 }
366 /* >8 End of l2fwd_crypto_send_burst. */
367
368 /* Crypto enqueue. 8< */
369 static int
l2fwd_crypto_enqueue(struct rte_crypto_op * op,struct l2fwd_crypto_params * cparams)370 l2fwd_crypto_enqueue(struct rte_crypto_op *op,
371 struct l2fwd_crypto_params *cparams)
372 {
373 unsigned lcore_id, len;
374 struct lcore_queue_conf *qconf;
375
376 lcore_id = rte_lcore_id();
377
378 qconf = &lcore_queue_conf[lcore_id];
379 len = qconf->op_buf[cparams->dev_id].len;
380 qconf->op_buf[cparams->dev_id].buffer[len] = op;
381 len++;
382
383 /* enough ops to be sent */
384 if (len == MAX_PKT_BURST) {
385 l2fwd_crypto_send_burst(qconf, MAX_PKT_BURST, cparams);
386 len = 0;
387 }
388
389 qconf->op_buf[cparams->dev_id].len = len;
390 return 0;
391 }
392 /* >8 End of crypto enqueue. */
393
394 static int
l2fwd_simple_crypto_enqueue(struct rte_mbuf * m,struct rte_crypto_op * op,struct l2fwd_crypto_params * cparams)395 l2fwd_simple_crypto_enqueue(struct rte_mbuf *m,
396 struct rte_crypto_op *op,
397 struct l2fwd_crypto_params *cparams)
398 {
399 struct rte_ether_hdr *eth_hdr;
400 struct rte_ipv4_hdr *ip_hdr;
401
402 uint32_t ipdata_offset, data_len;
403 uint32_t pad_len = 0;
404 char *padding;
405
406 eth_hdr = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
407
408 if (eth_hdr->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4))
409 return -1;
410
411 ipdata_offset = sizeof(struct rte_ether_hdr);
412
413 ip_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
414 ipdata_offset);
415
416 ipdata_offset += (ip_hdr->version_ihl & RTE_IPV4_HDR_IHL_MASK)
417 * RTE_IPV4_IHL_MULTIPLIER;
418
419
420 /* Zero pad data to be crypto'd so it is block aligned */
421 data_len = rte_pktmbuf_data_len(m) - ipdata_offset;
422
423 if ((cparams->do_hash || cparams->do_aead) && cparams->hash_verify)
424 data_len -= cparams->digest_length;
425
426 if (cparams->do_cipher) {
427 /*
428 * Following algorithms are block cipher algorithms,
429 * and might need padding
430 */
431 switch (cparams->cipher_algo) {
432 case RTE_CRYPTO_CIPHER_AES_CBC:
433 case RTE_CRYPTO_CIPHER_AES_ECB:
434 case RTE_CRYPTO_CIPHER_DES_CBC:
435 case RTE_CRYPTO_CIPHER_3DES_CBC:
436 case RTE_CRYPTO_CIPHER_3DES_ECB:
437 if (data_len % cparams->block_size)
438 pad_len = cparams->block_size -
439 (data_len % cparams->block_size);
440 break;
441 case RTE_CRYPTO_CIPHER_AES_XTS:
442 if (cparams->cipher_dataunit_len != 0 &&
443 (data_len % cparams->cipher_dataunit_len))
444 pad_len = cparams->cipher_dataunit_len -
445 (data_len % cparams->cipher_dataunit_len);
446 break;
447 default:
448 pad_len = 0;
449 }
450
451 if (pad_len) {
452 padding = rte_pktmbuf_append(m, pad_len);
453 if (unlikely(!padding))
454 return -1;
455
456 data_len += pad_len;
457 memset(padding, 0, pad_len);
458 }
459 }
460
461 /* Set crypto operation data parameters */
462 rte_crypto_op_attach_sym_session(op, cparams->session);
463
464 if (cparams->do_hash) {
465 if (cparams->auth_iv.length) {
466 uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op,
467 uint8_t *,
468 IV_OFFSET +
469 cparams->cipher_iv.length);
470 /*
471 * Copy IV at the end of the crypto operation,
472 * after the cipher IV, if added
473 */
474 rte_memcpy(iv_ptr, cparams->auth_iv.data,
475 cparams->auth_iv.length);
476 }
477 if (!cparams->hash_verify) {
478 /* Append space for digest to end of packet */
479 op->sym->auth.digest.data = (uint8_t *)rte_pktmbuf_append(m,
480 cparams->digest_length);
481 } else {
482 op->sym->auth.digest.data = rte_pktmbuf_mtod_offset(m,
483 uint8_t *, ipdata_offset + data_len);
484 }
485
486 op->sym->auth.digest.phys_addr = rte_pktmbuf_iova_offset(m,
487 rte_pktmbuf_pkt_len(m) - cparams->digest_length);
488
489 /* For wireless algorithms, offset/length must be in bits */
490 if (cparams->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
491 cparams->auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 ||
492 cparams->auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3) {
493 op->sym->auth.data.offset = ipdata_offset << 3;
494 op->sym->auth.data.length = data_len << 3;
495 } else {
496 op->sym->auth.data.offset = ipdata_offset;
497 op->sym->auth.data.length = data_len;
498 }
499 }
500
501 if (cparams->do_cipher) {
502 uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op, uint8_t *,
503 IV_OFFSET);
504 /* Copy IV at the end of the crypto operation */
505 rte_memcpy(iv_ptr, cparams->cipher_iv.data,
506 cparams->cipher_iv.length);
507
508 /* For wireless algorithms, offset/length must be in bits */
509 if (cparams->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
510 cparams->cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 ||
511 cparams->cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3) {
512 op->sym->cipher.data.offset = ipdata_offset << 3;
513 op->sym->cipher.data.length = data_len << 3;
514 } else {
515 op->sym->cipher.data.offset = ipdata_offset;
516 op->sym->cipher.data.length = data_len;
517 }
518 }
519
520 if (cparams->do_aead) {
521 uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op, uint8_t *,
522 IV_OFFSET);
523 /* Copy IV at the end of the crypto operation */
524 /*
525 * If doing AES-CCM, nonce is copied one byte
526 * after the start of IV field
527 */
528 if (cparams->aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
529 rte_memcpy(iv_ptr + 1, cparams->aead_iv.data,
530 cparams->aead_iv.length);
531 else
532 rte_memcpy(iv_ptr, cparams->aead_iv.data,
533 cparams->aead_iv.length);
534
535 op->sym->aead.data.offset = ipdata_offset;
536 op->sym->aead.data.length = data_len;
537
538 if (!cparams->hash_verify) {
539 /* Append space for digest to end of packet */
540 op->sym->aead.digest.data = (uint8_t *)rte_pktmbuf_append(m,
541 cparams->digest_length);
542 } else {
543 op->sym->aead.digest.data = rte_pktmbuf_mtod_offset(m,
544 uint8_t *, ipdata_offset + data_len);
545 }
546
547 op->sym->aead.digest.phys_addr = rte_pktmbuf_iova_offset(m,
548 rte_pktmbuf_pkt_len(m) - cparams->digest_length);
549
550 if (cparams->aad.length) {
551 op->sym->aead.aad.data = cparams->aad.data;
552 op->sym->aead.aad.phys_addr = cparams->aad.phys_addr;
553 }
554 }
555
556 op->sym->m_src = m;
557
558 return l2fwd_crypto_enqueue(op, cparams);
559 }
560
561
562 /* Send the burst of packets on an output interface */
563 static int
l2fwd_send_burst(struct lcore_queue_conf * qconf,unsigned n,uint16_t port)564 l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n,
565 uint16_t port)
566 {
567 struct rte_mbuf **pkt_buffer;
568 unsigned ret;
569
570 pkt_buffer = (struct rte_mbuf **)qconf->pkt_buf[port].buffer;
571
572 ret = rte_eth_tx_burst(port, 0, pkt_buffer, (uint16_t)n);
573 port_statistics[port].tx += ret;
574 if (unlikely(ret < n)) {
575 port_statistics[port].dropped += (n - ret);
576 do {
577 rte_pktmbuf_free(pkt_buffer[ret]);
578 } while (++ret < n);
579 }
580
581 return 0;
582 }
583
584 /* Enqueue packets for TX and prepare them to be sent. 8< */
585 static int
l2fwd_send_packet(struct rte_mbuf * m,uint16_t port)586 l2fwd_send_packet(struct rte_mbuf *m, uint16_t port)
587 {
588 unsigned lcore_id, len;
589 struct lcore_queue_conf *qconf;
590
591 lcore_id = rte_lcore_id();
592
593 qconf = &lcore_queue_conf[lcore_id];
594 len = qconf->pkt_buf[port].len;
595 qconf->pkt_buf[port].buffer[len] = m;
596 len++;
597
598 /* enough pkts to be sent */
599 if (unlikely(len == MAX_PKT_BURST)) {
600 l2fwd_send_burst(qconf, MAX_PKT_BURST, port);
601 len = 0;
602 }
603
604 qconf->pkt_buf[port].len = len;
605 return 0;
606 }
607 /* >8 End of Enqueuing packets for TX. */
608
609 static void
l2fwd_mac_updating(struct rte_mbuf * m,uint16_t dest_portid)610 l2fwd_mac_updating(struct rte_mbuf *m, uint16_t dest_portid)
611 {
612 struct rte_ether_hdr *eth;
613 void *tmp;
614
615 eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
616
617 /* 02:00:00:00:00:xx */
618 tmp = ð->dst_addr.addr_bytes[0];
619 *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dest_portid << 40);
620
621 /* src addr */
622 rte_ether_addr_copy(&l2fwd_ports_eth_addr[dest_portid], ð->src_addr);
623 }
624
625 static void
l2fwd_simple_forward(struct rte_mbuf * m,uint16_t portid,struct l2fwd_crypto_options * options)626 l2fwd_simple_forward(struct rte_mbuf *m, uint16_t portid,
627 struct l2fwd_crypto_options *options)
628 {
629 uint16_t dst_port;
630 uint32_t pad_len;
631 struct rte_ipv4_hdr *ip_hdr;
632 uint32_t ipdata_offset = sizeof(struct rte_ether_hdr);
633
634 ip_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *,
635 ipdata_offset);
636 dst_port = l2fwd_dst_ports[portid];
637
638 if (options->mac_updating)
639 l2fwd_mac_updating(m, dst_port);
640
641 if (options->auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY)
642 rte_pktmbuf_trim(m, options->auth_xform.auth.digest_length);
643
644 if (options->cipher_xform.cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
645 pad_len = m->pkt_len - rte_be_to_cpu_16(ip_hdr->total_length) -
646 ipdata_offset;
647 rte_pktmbuf_trim(m, pad_len);
648 }
649
650 l2fwd_send_packet(m, dst_port);
651 }
652
653 /** Generate random key */
654 static void
generate_random_key(uint8_t * key,unsigned length)655 generate_random_key(uint8_t *key, unsigned length)
656 {
657 int fd;
658 int ret;
659
660 fd = open("/dev/urandom", O_RDONLY);
661 if (fd < 0)
662 rte_exit(EXIT_FAILURE, "Failed to generate random key\n");
663
664 ret = read(fd, key, length);
665 close(fd);
666
667 if (ret != (signed)length)
668 rte_exit(EXIT_FAILURE, "Failed to generate random key\n");
669 }
670
671 /* Session is created and is later attached to the crypto operation. 8< */
672 static void *
initialize_crypto_session(struct l2fwd_crypto_options * options,uint8_t cdev_id)673 initialize_crypto_session(struct l2fwd_crypto_options *options, uint8_t cdev_id)
674 {
675 struct rte_crypto_sym_xform *first_xform;
676 int retval = rte_cryptodev_socket_id(cdev_id);
677
678 if (retval < 0)
679 return NULL;
680
681 uint8_t socket_id = (uint8_t) retval;
682
683 if (options->xform_chain == L2FWD_CRYPTO_AEAD) {
684 first_xform = &options->aead_xform;
685 } else if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH) {
686 first_xform = &options->cipher_xform;
687 first_xform->next = &options->auth_xform;
688 } else if (options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER) {
689 first_xform = &options->auth_xform;
690 first_xform->next = &options->cipher_xform;
691 } else if (options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
692 first_xform = &options->cipher_xform;
693 } else {
694 first_xform = &options->auth_xform;
695 }
696
697 return rte_cryptodev_sym_session_create(cdev_id, first_xform,
698 session_pool_socket[socket_id].sess_mp);
699 }
700 /* >8 End of creation of session. */
701
702 static void
703 l2fwd_crypto_options_print(struct l2fwd_crypto_options *options);
704
705 /* main processing loop */
706 static void
l2fwd_main_loop(struct l2fwd_crypto_options * options)707 l2fwd_main_loop(struct l2fwd_crypto_options *options)
708 {
709 struct rte_mbuf *m, *pkts_burst[MAX_PKT_BURST];
710 struct rte_crypto_op *ops_burst[MAX_PKT_BURST];
711
712 unsigned lcore_id = rte_lcore_id();
713 uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
714 unsigned int i, j, nb_rx, len;
715 uint16_t portid;
716 struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id];
717 const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
718 US_PER_S * BURST_TX_DRAIN_US;
719 struct l2fwd_crypto_params *cparams;
720 struct l2fwd_crypto_params port_cparams[qconf->nb_crypto_devs];
721 void *session;
722
723 if (qconf->nb_rx_ports == 0) {
724 RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id);
725 return;
726 }
727
728 RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);
729
730 for (i = 0; i < qconf->nb_rx_ports; i++) {
731
732 portid = qconf->rx_port_list[i];
733 RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,
734 portid);
735 }
736
737 for (i = 0; i < qconf->nb_crypto_devs; i++) {
738 port_cparams[i].do_cipher = 0;
739 port_cparams[i].do_hash = 0;
740 port_cparams[i].do_aead = 0;
741
742 switch (options->xform_chain) {
743 case L2FWD_CRYPTO_AEAD:
744 port_cparams[i].do_aead = 1;
745 break;
746 case L2FWD_CRYPTO_CIPHER_HASH:
747 case L2FWD_CRYPTO_HASH_CIPHER:
748 port_cparams[i].do_cipher = 1;
749 port_cparams[i].do_hash = 1;
750 break;
751 case L2FWD_CRYPTO_HASH_ONLY:
752 port_cparams[i].do_hash = 1;
753 break;
754 case L2FWD_CRYPTO_CIPHER_ONLY:
755 port_cparams[i].do_cipher = 1;
756 break;
757 }
758
759 port_cparams[i].dev_id = qconf->cryptodev_list[i];
760 port_cparams[i].qp_id = 0;
761
762 port_cparams[i].block_size = options->block_size;
763
764 if (port_cparams[i].do_hash) {
765 port_cparams[i].auth_iv.data = options->auth_iv.data;
766 port_cparams[i].auth_iv.length = options->auth_iv.length;
767 if (!options->auth_iv_param)
768 generate_random_key(port_cparams[i].auth_iv.data,
769 port_cparams[i].auth_iv.length);
770 if (options->auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY)
771 port_cparams[i].hash_verify = 1;
772 else
773 port_cparams[i].hash_verify = 0;
774
775 port_cparams[i].auth_algo = options->auth_xform.auth.algo;
776 port_cparams[i].digest_length =
777 options->auth_xform.auth.digest_length;
778 /* Set IV parameters */
779 if (options->auth_iv.length) {
780 options->auth_xform.auth.iv.offset =
781 IV_OFFSET + options->cipher_iv.length;
782 options->auth_xform.auth.iv.length =
783 options->auth_iv.length;
784 }
785 }
786
787 if (port_cparams[i].do_aead) {
788 port_cparams[i].aead_iv.data = options->aead_iv.data;
789 port_cparams[i].aead_iv.length = options->aead_iv.length;
790 if (!options->aead_iv_param)
791 generate_random_key(port_cparams[i].aead_iv.data,
792 port_cparams[i].aead_iv.length);
793 port_cparams[i].aead_algo = options->aead_xform.aead.algo;
794 port_cparams[i].digest_length =
795 options->aead_xform.aead.digest_length;
796 if (options->aead_xform.aead.aad_length) {
797 port_cparams[i].aad.data = options->aad.data;
798 port_cparams[i].aad.phys_addr = options->aad.phys_addr;
799 port_cparams[i].aad.length = options->aad.length;
800 if (!options->aad_param)
801 generate_random_key(port_cparams[i].aad.data,
802 port_cparams[i].aad.length);
803 /*
804 * If doing AES-CCM, first 18 bytes has to be reserved,
805 * and actual AAD should start from byte 18
806 */
807 if (port_cparams[i].aead_algo == RTE_CRYPTO_AEAD_AES_CCM)
808 memmove(port_cparams[i].aad.data + 18,
809 port_cparams[i].aad.data,
810 port_cparams[i].aad.length);
811
812 } else
813 port_cparams[i].aad.length = 0;
814
815 if (options->aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_DECRYPT)
816 port_cparams[i].hash_verify = 1;
817 else
818 port_cparams[i].hash_verify = 0;
819
820 /* Set IV parameters */
821 options->aead_xform.aead.iv.offset = IV_OFFSET;
822 options->aead_xform.aead.iv.length = options->aead_iv.length;
823 }
824
825 if (port_cparams[i].do_cipher) {
826 port_cparams[i].cipher_iv.data = options->cipher_iv.data;
827 port_cparams[i].cipher_iv.length = options->cipher_iv.length;
828 if (!options->cipher_iv_param)
829 generate_random_key(port_cparams[i].cipher_iv.data,
830 port_cparams[i].cipher_iv.length);
831
832 port_cparams[i].cipher_algo = options->cipher_xform.cipher.algo;
833 port_cparams[i].cipher_dataunit_len =
834 options->cipher_xform.cipher.dataunit_len;
835 /* Set IV parameters */
836 options->cipher_xform.cipher.iv.offset = IV_OFFSET;
837 options->cipher_xform.cipher.iv.length =
838 options->cipher_iv.length;
839 }
840
841 session = initialize_crypto_session(options,
842 port_cparams[i].dev_id);
843 if (session == NULL)
844 rte_exit(EXIT_FAILURE, "Failed to initialize crypto session\n");
845
846 port_cparams[i].session = session;
847
848 RTE_LOG(INFO, L2FWD, " -- lcoreid=%u cryptoid=%u\n", lcore_id,
849 port_cparams[i].dev_id);
850 }
851
852 l2fwd_crypto_options_print(options);
853
854 /*
855 * Initialize previous tsc timestamp before the loop,
856 * to avoid showing the port statistics immediately,
857 * so user can see the crypto information.
858 */
859 prev_tsc = rte_rdtsc();
860 while (1) {
861
862 cur_tsc = rte_rdtsc();
863
864 /*
865 * Crypto device/TX burst queue drain
866 */
867 diff_tsc = cur_tsc - prev_tsc;
868 if (unlikely(diff_tsc > drain_tsc)) {
869 /* Enqueue all crypto ops remaining in buffers */
870 for (i = 0; i < qconf->nb_crypto_devs; i++) {
871 cparams = &port_cparams[i];
872 len = qconf->op_buf[cparams->dev_id].len;
873 l2fwd_crypto_send_burst(qconf, len, cparams);
874 qconf->op_buf[cparams->dev_id].len = 0;
875 }
876 /* Transmit all packets remaining in buffers */
877 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
878 if (qconf->pkt_buf[portid].len == 0)
879 continue;
880 l2fwd_send_burst(&lcore_queue_conf[lcore_id],
881 qconf->pkt_buf[portid].len,
882 portid);
883 qconf->pkt_buf[portid].len = 0;
884 }
885
886 /* if timer is enabled */
887 if (options->refresh_period > 0) {
888
889 /* advance the timer */
890 timer_tsc += diff_tsc;
891
892 /* if timer has reached its timeout */
893 if (unlikely(timer_tsc >=
894 options->refresh_period)) {
895
896 /* do this only on main core */
897 if (lcore_id == rte_get_main_lcore()) {
898 print_stats();
899 timer_tsc = 0;
900 }
901 }
902 }
903
904 prev_tsc = cur_tsc;
905 }
906
907 /*
908 * Read packet from RX queues
909 */
910 for (i = 0; i < qconf->nb_rx_ports; i++) {
911 portid = qconf->rx_port_list[i];
912
913 cparams = &port_cparams[i];
914
915 nb_rx = rte_eth_rx_burst(portid, 0,
916 pkts_burst, MAX_PKT_BURST);
917 if (unlikely(signal_received))
918 return;
919
920 port_statistics[portid].rx += nb_rx;
921
922 /* Allocate and fillcrypto operations. 8< */
923 if (nb_rx) {
924 /*
925 * If we can't allocate a crypto_ops, then drop
926 * the rest of the burst and dequeue and
927 * process the packets to free offload structs
928 */
929 if (rte_crypto_op_bulk_alloc(
930 l2fwd_crypto_op_pool,
931 RTE_CRYPTO_OP_TYPE_SYMMETRIC,
932 ops_burst, nb_rx) !=
933 nb_rx) {
934 for (j = 0; j < nb_rx; j++)
935 rte_pktmbuf_free(pkts_burst[j]);
936
937 nb_rx = 0;
938 }
939 /* >8 End of crypto operation allocated and filled. */
940
941 /* Enqueue packets from Crypto device*/
942 for (j = 0; j < nb_rx; j++) {
943 m = pkts_burst[j];
944
945 l2fwd_simple_crypto_enqueue(m,
946 ops_burst[j], cparams);
947 }
948 }
949
950 /* Dequeue packets from Crypto device. 8< */
951 do {
952 nb_rx = rte_cryptodev_dequeue_burst(
953 cparams->dev_id, cparams->qp_id,
954 ops_burst, MAX_PKT_BURST);
955
956 crypto_statistics[cparams->dev_id].dequeued +=
957 nb_rx;
958
959 /* Forward crypto'd packets */
960 for (j = 0; j < nb_rx; j++) {
961 m = ops_burst[j]->sym->m_src;
962
963 rte_crypto_op_free(ops_burst[j]);
964 l2fwd_simple_forward(m, portid,
965 options);
966 }
967 } while (nb_rx == MAX_PKT_BURST);
968 /* >8 End of dequeue packets from crypto device. */
969 }
970 }
971 }
972
973 static int
l2fwd_launch_one_lcore(void * arg)974 l2fwd_launch_one_lcore(void *arg)
975 {
976 l2fwd_main_loop((struct l2fwd_crypto_options *)arg);
977 return 0;
978 }
979
980 /* Display command line arguments usage */
981 static void
l2fwd_crypto_usage(const char * prgname)982 l2fwd_crypto_usage(const char *prgname)
983 {
984 printf("%s [EAL options] --\n"
985 " -p PORTMASK: hexadecimal bitmask of ports to configure\n"
986 " -q NQ: number of queue (=ports) per lcore (default is 1)\n"
987 " -s manage all ports from single lcore\n"
988 " -T PERIOD: statistics will be refreshed each PERIOD seconds"
989 " (0 to disable, 10 default, 86400 maximum)\n"
990
991 " --cdev_type HW / SW / ANY\n"
992 " --chain HASH_CIPHER / CIPHER_HASH / CIPHER_ONLY /"
993 " HASH_ONLY / AEAD\n"
994
995 " --cipher_algo ALGO\n"
996 " --cipher_op ENCRYPT / DECRYPT\n"
997 " --cipher_key KEY (bytes separated with \":\")\n"
998 " --cipher_key_random_size SIZE: size of cipher key when generated randomly\n"
999 " --cipher_iv IV (bytes separated with \":\")\n"
1000 " --cipher_iv_random_size SIZE: size of cipher IV when generated randomly\n"
1001 " --cipher_dataunit_len SIZE: length of the algorithm data-unit\n"
1002
1003 " --auth_algo ALGO\n"
1004 " --auth_op GENERATE / VERIFY\n"
1005 " --auth_key KEY (bytes separated with \":\")\n"
1006 " --auth_key_random_size SIZE: size of auth key when generated randomly\n"
1007 " --auth_iv IV (bytes separated with \":\")\n"
1008 " --auth_iv_random_size SIZE: size of auth IV when generated randomly\n"
1009
1010 " --aead_algo ALGO\n"
1011 " --aead_op ENCRYPT / DECRYPT\n"
1012 " --aead_key KEY (bytes separated with \":\")\n"
1013 " --aead_key_random_size SIZE: size of AEAD key when generated randomly\n"
1014 " --aead_iv IV (bytes separated with \":\")\n"
1015 " --aead_iv_random_size SIZE: size of AEAD IV when generated randomly\n"
1016 " --aad AAD (bytes separated with \":\")\n"
1017 " --aad_random_size SIZE: size of AAD when generated randomly\n"
1018
1019 " --digest_size SIZE: size of digest to be generated/verified\n"
1020
1021 " --sessionless\n"
1022 " --cryptodev_mask MASK: hexadecimal bitmask of crypto devices to configure\n"
1023
1024 " --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n"
1025 " When enabled:\n"
1026 " - The source MAC address is replaced by the TX port MAC address\n"
1027 " - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n",
1028 prgname);
1029 }
1030
1031 /** Parse crypto device type command line argument */
1032 static int
parse_cryptodev_type(enum cdev_type * type,char * optarg)1033 parse_cryptodev_type(enum cdev_type *type, char *optarg)
1034 {
1035 if (strcmp("HW", optarg) == 0) {
1036 *type = CDEV_TYPE_HW;
1037 return 0;
1038 } else if (strcmp("SW", optarg) == 0) {
1039 *type = CDEV_TYPE_SW;
1040 return 0;
1041 } else if (strcmp("ANY", optarg) == 0) {
1042 *type = CDEV_TYPE_ANY;
1043 return 0;
1044 }
1045
1046 return -1;
1047 }
1048
1049 /** Parse crypto chain xform command line argument */
1050 static int
parse_crypto_opt_chain(struct l2fwd_crypto_options * options,char * optarg)1051 parse_crypto_opt_chain(struct l2fwd_crypto_options *options, char *optarg)
1052 {
1053 if (strcmp("CIPHER_HASH", optarg) == 0) {
1054 options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;
1055 return 0;
1056 } else if (strcmp("HASH_CIPHER", optarg) == 0) {
1057 options->xform_chain = L2FWD_CRYPTO_HASH_CIPHER;
1058 return 0;
1059 } else if (strcmp("CIPHER_ONLY", optarg) == 0) {
1060 options->xform_chain = L2FWD_CRYPTO_CIPHER_ONLY;
1061 return 0;
1062 } else if (strcmp("HASH_ONLY", optarg) == 0) {
1063 options->xform_chain = L2FWD_CRYPTO_HASH_ONLY;
1064 return 0;
1065 } else if (strcmp("AEAD", optarg) == 0) {
1066 options->xform_chain = L2FWD_CRYPTO_AEAD;
1067 return 0;
1068 }
1069
1070 return -1;
1071 }
1072
1073 /** Parse crypto cipher algo option command line argument */
1074 static int
parse_cipher_algo(enum rte_crypto_cipher_algorithm * algo,char * optarg)1075 parse_cipher_algo(enum rte_crypto_cipher_algorithm *algo, char *optarg)
1076 {
1077
1078 if (rte_cryptodev_get_cipher_algo_enum(algo, optarg) < 0) {
1079 RTE_LOG(ERR, USER1, "Cipher algorithm specified "
1080 "not supported!\n");
1081 return -1;
1082 }
1083
1084 return 0;
1085 }
1086
1087 /** Parse crypto cipher operation command line argument */
1088 static int
parse_cipher_op(enum rte_crypto_cipher_operation * op,char * optarg)1089 parse_cipher_op(enum rte_crypto_cipher_operation *op, char *optarg)
1090 {
1091 if (strcmp("ENCRYPT", optarg) == 0) {
1092 *op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
1093 return 0;
1094 } else if (strcmp("DECRYPT", optarg) == 0) {
1095 *op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
1096 return 0;
1097 }
1098
1099 printf("Cipher operation not supported!\n");
1100 return -1;
1101 }
1102
1103 /** Parse bytes from command line argument */
1104 static int
parse_bytes(uint8_t * data,char * input_arg,uint16_t max_size)1105 parse_bytes(uint8_t *data, char *input_arg, uint16_t max_size)
1106 {
1107 unsigned byte_count;
1108 char *token;
1109
1110 errno = 0;
1111 for (byte_count = 0, token = strtok(input_arg, ":");
1112 (byte_count < max_size) && (token != NULL);
1113 token = strtok(NULL, ":")) {
1114
1115 int number = (int)strtol(token, NULL, 16);
1116
1117 if (errno == EINVAL || errno == ERANGE || number > 0xFF)
1118 return -1;
1119
1120 data[byte_count++] = (uint8_t)number;
1121 }
1122
1123 return byte_count;
1124 }
1125
1126 /** Parse size param*/
1127 static int
parse_size(int * size,const char * q_arg)1128 parse_size(int *size, const char *q_arg)
1129 {
1130 char *end = NULL;
1131 unsigned long n;
1132
1133 /* parse hexadecimal string */
1134 n = strtoul(q_arg, &end, 10);
1135 if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1136 n = 0;
1137
1138 if (n == 0) {
1139 printf("invalid size\n");
1140 return -1;
1141 }
1142
1143 *size = n;
1144 return 0;
1145 }
1146
1147 /** Parse crypto cipher operation command line argument */
1148 static int
parse_auth_algo(enum rte_crypto_auth_algorithm * algo,char * optarg)1149 parse_auth_algo(enum rte_crypto_auth_algorithm *algo, char *optarg)
1150 {
1151 if (rte_cryptodev_get_auth_algo_enum(algo, optarg) < 0) {
1152 RTE_LOG(ERR, USER1, "Authentication algorithm specified "
1153 "not supported!\n");
1154 return -1;
1155 }
1156
1157 return 0;
1158 }
1159
1160 static int
parse_auth_op(enum rte_crypto_auth_operation * op,char * optarg)1161 parse_auth_op(enum rte_crypto_auth_operation *op, char *optarg)
1162 {
1163 if (strcmp("VERIFY", optarg) == 0) {
1164 *op = RTE_CRYPTO_AUTH_OP_VERIFY;
1165 return 0;
1166 } else if (strcmp("GENERATE", optarg) == 0) {
1167 *op = RTE_CRYPTO_AUTH_OP_GENERATE;
1168 return 0;
1169 }
1170
1171 printf("Authentication operation specified not supported!\n");
1172 return -1;
1173 }
1174
1175 static int
parse_aead_algo(enum rte_crypto_aead_algorithm * algo,char * optarg)1176 parse_aead_algo(enum rte_crypto_aead_algorithm *algo, char *optarg)
1177 {
1178 if (rte_cryptodev_get_aead_algo_enum(algo, optarg) < 0) {
1179 RTE_LOG(ERR, USER1, "AEAD algorithm specified "
1180 "not supported!\n");
1181 return -1;
1182 }
1183
1184 return 0;
1185 }
1186
1187 static int
parse_aead_op(enum rte_crypto_aead_operation * op,char * optarg)1188 parse_aead_op(enum rte_crypto_aead_operation *op, char *optarg)
1189 {
1190 if (strcmp("ENCRYPT", optarg) == 0) {
1191 *op = RTE_CRYPTO_AEAD_OP_ENCRYPT;
1192 return 0;
1193 } else if (strcmp("DECRYPT", optarg) == 0) {
1194 *op = RTE_CRYPTO_AEAD_OP_DECRYPT;
1195 return 0;
1196 }
1197
1198 printf("AEAD operation specified not supported!\n");
1199 return -1;
1200 }
1201 static int
parse_cryptodev_mask(struct l2fwd_crypto_options * options,const char * q_arg)1202 parse_cryptodev_mask(struct l2fwd_crypto_options *options,
1203 const char *q_arg)
1204 {
1205 char *end = NULL;
1206 uint64_t pm;
1207
1208 /* parse hexadecimal string */
1209 pm = strtoul(q_arg, &end, 16);
1210 if ((pm == '\0') || (end == NULL) || (*end != '\0'))
1211 pm = 0;
1212
1213 options->cryptodev_mask = pm;
1214 if (options->cryptodev_mask == 0) {
1215 printf("invalid cryptodev_mask specified\n");
1216 return -1;
1217 }
1218
1219 return 0;
1220 }
1221
1222 /** Parse long options */
1223 static int
l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options * options,struct option * lgopts,int option_index)1224 l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,
1225 struct option *lgopts, int option_index)
1226 {
1227 int retval;
1228 int val;
1229
1230 if (strcmp(lgopts[option_index].name, "cdev_type") == 0) {
1231 retval = parse_cryptodev_type(&options->type, optarg);
1232 if (retval == 0)
1233 strlcpy(options->string_type, optarg, MAX_STR_LEN);
1234 return retval;
1235 }
1236
1237 else if (strcmp(lgopts[option_index].name, "chain") == 0)
1238 return parse_crypto_opt_chain(options, optarg);
1239
1240 /* Cipher options */
1241 else if (strcmp(lgopts[option_index].name, "cipher_algo") == 0)
1242 return parse_cipher_algo(&options->cipher_xform.cipher.algo,
1243 optarg);
1244
1245 else if (strcmp(lgopts[option_index].name, "cipher_op") == 0)
1246 return parse_cipher_op(&options->cipher_xform.cipher.op,
1247 optarg);
1248
1249 else if (strcmp(lgopts[option_index].name, "cipher_key") == 0) {
1250 options->ckey_param = 1;
1251 options->cipher_xform.cipher.key.length =
1252 parse_bytes(options->cipher_key, optarg, MAX_KEY_SIZE);
1253 if (options->cipher_xform.cipher.key.length > 0)
1254 return 0;
1255 else
1256 return -1;
1257 }
1258
1259 else if (strcmp(lgopts[option_index].name, "cipher_dataunit_len") == 0) {
1260 retval = parse_size(&val, optarg);
1261 if (retval == 0 && val >= 0) {
1262 options->cipher_xform.cipher.dataunit_len =
1263 (uint32_t)val;
1264 return 0;
1265 } else
1266 return -1;
1267 }
1268
1269 else if (strcmp(lgopts[option_index].name, "cipher_key_random_size") == 0)
1270 return parse_size(&options->ckey_random_size, optarg);
1271
1272 else if (strcmp(lgopts[option_index].name, "cipher_iv") == 0) {
1273 options->cipher_iv_param = 1;
1274 options->cipher_iv.length =
1275 parse_bytes(options->cipher_iv.data, optarg, MAX_IV_SIZE);
1276 if (options->cipher_iv.length > 0)
1277 return 0;
1278 else
1279 return -1;
1280 }
1281
1282 else if (strcmp(lgopts[option_index].name, "cipher_iv_random_size") == 0)
1283 return parse_size(&options->cipher_iv_random_size, optarg);
1284
1285 /* Authentication options */
1286 else if (strcmp(lgopts[option_index].name, "auth_algo") == 0) {
1287 return parse_auth_algo(&options->auth_xform.auth.algo,
1288 optarg);
1289 }
1290
1291 else if (strcmp(lgopts[option_index].name, "auth_op") == 0)
1292 return parse_auth_op(&options->auth_xform.auth.op,
1293 optarg);
1294
1295 else if (strcmp(lgopts[option_index].name, "auth_key") == 0) {
1296 options->akey_param = 1;
1297 options->auth_xform.auth.key.length =
1298 parse_bytes(options->auth_key, optarg, MAX_KEY_SIZE);
1299 if (options->auth_xform.auth.key.length > 0)
1300 return 0;
1301 else
1302 return -1;
1303 }
1304
1305 else if (strcmp(lgopts[option_index].name, "auth_key_random_size") == 0) {
1306 return parse_size(&options->akey_random_size, optarg);
1307 }
1308
1309 else if (strcmp(lgopts[option_index].name, "auth_iv") == 0) {
1310 options->auth_iv_param = 1;
1311 options->auth_iv.length =
1312 parse_bytes(options->auth_iv.data, optarg, MAX_IV_SIZE);
1313 if (options->auth_iv.length > 0)
1314 return 0;
1315 else
1316 return -1;
1317 }
1318
1319 else if (strcmp(lgopts[option_index].name, "auth_iv_random_size") == 0)
1320 return parse_size(&options->auth_iv_random_size, optarg);
1321
1322 /* AEAD options */
1323 else if (strcmp(lgopts[option_index].name, "aead_algo") == 0) {
1324 return parse_aead_algo(&options->aead_xform.aead.algo,
1325 optarg);
1326 }
1327
1328 else if (strcmp(lgopts[option_index].name, "aead_op") == 0)
1329 return parse_aead_op(&options->aead_xform.aead.op,
1330 optarg);
1331
1332 else if (strcmp(lgopts[option_index].name, "aead_key") == 0) {
1333 options->aead_key_param = 1;
1334 options->aead_xform.aead.key.length =
1335 parse_bytes(options->aead_key, optarg, MAX_KEY_SIZE);
1336 if (options->aead_xform.aead.key.length > 0)
1337 return 0;
1338 else
1339 return -1;
1340 }
1341
1342 else if (strcmp(lgopts[option_index].name, "aead_key_random_size") == 0)
1343 return parse_size(&options->aead_key_random_size, optarg);
1344
1345
1346 else if (strcmp(lgopts[option_index].name, "aead_iv") == 0) {
1347 options->aead_iv_param = 1;
1348 options->aead_iv.length =
1349 parse_bytes(options->aead_iv.data, optarg, MAX_IV_SIZE);
1350 if (options->aead_iv.length > 0)
1351 return 0;
1352 else
1353 return -1;
1354 }
1355
1356 else if (strcmp(lgopts[option_index].name, "aead_iv_random_size") == 0)
1357 return parse_size(&options->aead_iv_random_size, optarg);
1358
1359 else if (strcmp(lgopts[option_index].name, "aad") == 0) {
1360 options->aad_param = 1;
1361 options->aad.length =
1362 parse_bytes(options->aad.data, optarg, MAX_AAD_SIZE);
1363 if (options->aad.length > 0)
1364 return 0;
1365 else
1366 return -1;
1367 }
1368
1369 else if (strcmp(lgopts[option_index].name, "aad_random_size") == 0) {
1370 return parse_size(&options->aad_random_size, optarg);
1371 }
1372
1373 else if (strcmp(lgopts[option_index].name, "digest_size") == 0) {
1374 return parse_size(&options->digest_size, optarg);
1375 }
1376
1377 else if (strcmp(lgopts[option_index].name, "sessionless") == 0) {
1378 options->sessionless = 1;
1379 return 0;
1380 }
1381
1382 else if (strcmp(lgopts[option_index].name, "cryptodev_mask") == 0)
1383 return parse_cryptodev_mask(options, optarg);
1384
1385 else if (strcmp(lgopts[option_index].name, "mac-updating") == 0) {
1386 options->mac_updating = 1;
1387 return 0;
1388 }
1389
1390 else if (strcmp(lgopts[option_index].name, "no-mac-updating") == 0) {
1391 options->mac_updating = 0;
1392 return 0;
1393 }
1394
1395 return -1;
1396 }
1397
1398 /** Parse port mask */
1399 static int
l2fwd_crypto_parse_portmask(struct l2fwd_crypto_options * options,const char * q_arg)1400 l2fwd_crypto_parse_portmask(struct l2fwd_crypto_options *options,
1401 const char *q_arg)
1402 {
1403 char *end = NULL;
1404 unsigned long pm;
1405
1406 /* parse hexadecimal string */
1407 pm = strtoul(q_arg, &end, 16);
1408 if ((pm == '\0') || (end == NULL) || (*end != '\0'))
1409 pm = 0;
1410
1411 options->portmask = pm;
1412 if (options->portmask == 0) {
1413 printf("invalid portmask specified\n");
1414 return -1;
1415 }
1416
1417 return pm;
1418 }
1419
1420 /** Parse number of queues */
1421 static int
l2fwd_crypto_parse_nqueue(struct l2fwd_crypto_options * options,const char * q_arg)1422 l2fwd_crypto_parse_nqueue(struct l2fwd_crypto_options *options,
1423 const char *q_arg)
1424 {
1425 char *end = NULL;
1426 unsigned long n;
1427
1428 /* parse hexadecimal string */
1429 n = strtoul(q_arg, &end, 10);
1430 if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1431 n = 0;
1432 else if (n >= MAX_RX_QUEUE_PER_LCORE)
1433 n = 0;
1434
1435 options->nb_ports_per_lcore = n;
1436 if (options->nb_ports_per_lcore == 0) {
1437 printf("invalid number of ports selected\n");
1438 return -1;
1439 }
1440
1441 return 0;
1442 }
1443
1444 /** Parse timer period */
1445 static int
l2fwd_crypto_parse_timer_period(struct l2fwd_crypto_options * options,const char * q_arg)1446 l2fwd_crypto_parse_timer_period(struct l2fwd_crypto_options *options,
1447 const char *q_arg)
1448 {
1449 char *end = NULL;
1450 unsigned long n;
1451
1452 /* parse number string */
1453 n = (unsigned)strtol(q_arg, &end, 10);
1454 if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1455 n = 0;
1456
1457 if (n >= MAX_TIMER_PERIOD) {
1458 printf("Warning refresh period specified %lu is greater than "
1459 "max value %lu! using max value",
1460 n, MAX_TIMER_PERIOD);
1461 n = MAX_TIMER_PERIOD;
1462 }
1463
1464 options->refresh_period = n * 1000 * TIMER_MILLISECOND;
1465
1466 return 0;
1467 }
1468
1469 /** Generate default options for application */
1470 static void
l2fwd_crypto_default_options(struct l2fwd_crypto_options * options)1471 l2fwd_crypto_default_options(struct l2fwd_crypto_options *options)
1472 {
1473 options->portmask = 0xffffffff;
1474 options->nb_ports_per_lcore = 1;
1475 options->refresh_period = DEFAULT_TIMER_PERIOD *
1476 TIMER_MILLISECOND * 1000;
1477 options->single_lcore = 0;
1478 options->sessionless = 0;
1479
1480 options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;
1481
1482 /* Cipher Data */
1483 options->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1484 options->cipher_xform.next = NULL;
1485 options->ckey_param = 0;
1486 options->ckey_random_size = -1;
1487 options->cipher_xform.cipher.key.length = 0;
1488 options->cipher_iv_param = 0;
1489 options->cipher_iv_random_size = -1;
1490 options->cipher_iv.length = 0;
1491
1492 options->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
1493 options->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
1494 options->cipher_xform.cipher.dataunit_len = 0;
1495
1496 /* Authentication Data */
1497 options->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
1498 options->auth_xform.next = NULL;
1499 options->akey_param = 0;
1500 options->akey_random_size = -1;
1501 options->auth_xform.auth.key.length = 0;
1502 options->auth_iv_param = 0;
1503 options->auth_iv_random_size = -1;
1504 options->auth_iv.length = 0;
1505
1506 options->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
1507 options->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
1508
1509 /* AEAD Data */
1510 options->aead_xform.type = RTE_CRYPTO_SYM_XFORM_AEAD;
1511 options->aead_xform.next = NULL;
1512 options->aead_key_param = 0;
1513 options->aead_key_random_size = -1;
1514 options->aead_xform.aead.key.length = 0;
1515 options->aead_iv_param = 0;
1516 options->aead_iv_random_size = -1;
1517 options->aead_iv.length = 0;
1518
1519 options->aead_xform.aead.algo = RTE_CRYPTO_AEAD_AES_GCM;
1520 options->aead_xform.aead.op = RTE_CRYPTO_AEAD_OP_ENCRYPT;
1521
1522 options->aad_param = 0;
1523 options->aad_random_size = -1;
1524 options->aad.length = 0;
1525
1526 options->digest_size = -1;
1527
1528 options->type = CDEV_TYPE_ANY;
1529 options->cryptodev_mask = UINT64_MAX;
1530
1531 options->mac_updating = 1;
1532 }
1533
1534 static void
display_cipher_info(struct l2fwd_crypto_options * options)1535 display_cipher_info(struct l2fwd_crypto_options *options)
1536 {
1537 printf("\n---- Cipher information ---\n");
1538 printf("Algorithm: %s\n",
1539 rte_cryptodev_get_cipher_algo_string(options->cipher_xform.cipher.algo));
1540 rte_hexdump(stdout, "Cipher key:",
1541 options->cipher_xform.cipher.key.data,
1542 options->cipher_xform.cipher.key.length);
1543 rte_hexdump(stdout, "IV:", options->cipher_iv.data, options->cipher_iv.length);
1544 }
1545
1546 static void
display_auth_info(struct l2fwd_crypto_options * options)1547 display_auth_info(struct l2fwd_crypto_options *options)
1548 {
1549 printf("\n---- Authentication information ---\n");
1550 printf("Algorithm: %s\n",
1551 rte_cryptodev_get_auth_algo_string(options->auth_xform.auth.algo));
1552 rte_hexdump(stdout, "Auth key:",
1553 options->auth_xform.auth.key.data,
1554 options->auth_xform.auth.key.length);
1555 rte_hexdump(stdout, "IV:", options->auth_iv.data, options->auth_iv.length);
1556 }
1557
1558 static void
display_aead_info(struct l2fwd_crypto_options * options)1559 display_aead_info(struct l2fwd_crypto_options *options)
1560 {
1561 printf("\n---- AEAD information ---\n");
1562 printf("Algorithm: %s\n",
1563 rte_cryptodev_get_aead_algo_string(options->aead_xform.aead.algo));
1564 rte_hexdump(stdout, "AEAD key:",
1565 options->aead_xform.aead.key.data,
1566 options->aead_xform.aead.key.length);
1567 rte_hexdump(stdout, "IV:", options->aead_iv.data, options->aead_iv.length);
1568 rte_hexdump(stdout, "AAD:", options->aad.data, options->aad.length);
1569 }
1570
1571 static void
l2fwd_crypto_options_print(struct l2fwd_crypto_options * options)1572 l2fwd_crypto_options_print(struct l2fwd_crypto_options *options)
1573 {
1574 char string_cipher_op[MAX_STR_LEN];
1575 char string_auth_op[MAX_STR_LEN];
1576 char string_aead_op[MAX_STR_LEN];
1577
1578 if (options->cipher_xform.cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
1579 strcpy(string_cipher_op, "Encrypt");
1580 else
1581 strcpy(string_cipher_op, "Decrypt");
1582
1583 if (options->auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_GENERATE)
1584 strcpy(string_auth_op, "Auth generate");
1585 else
1586 strcpy(string_auth_op, "Auth verify");
1587
1588 if (options->aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_ENCRYPT)
1589 strcpy(string_aead_op, "Authenticated encryption");
1590 else
1591 strcpy(string_aead_op, "Authenticated decryption");
1592
1593
1594 printf("Options:-\nn");
1595 printf("portmask: %x\n", options->portmask);
1596 printf("ports per lcore: %u\n", options->nb_ports_per_lcore);
1597 printf("refresh period : %u\n", options->refresh_period);
1598 printf("single lcore mode: %s\n",
1599 options->single_lcore ? "enabled" : "disabled");
1600 printf("stats_printing: %s\n",
1601 options->refresh_period == 0 ? "disabled" : "enabled");
1602
1603 printf("sessionless crypto: %s\n",
1604 options->sessionless ? "enabled" : "disabled");
1605
1606 if (options->ckey_param && (options->ckey_random_size != -1))
1607 printf("Cipher key already parsed, ignoring size of random key\n");
1608
1609 if (options->akey_param && (options->akey_random_size != -1))
1610 printf("Auth key already parsed, ignoring size of random key\n");
1611
1612 if (options->cipher_iv_param && (options->cipher_iv_random_size != -1))
1613 printf("Cipher IV already parsed, ignoring size of random IV\n");
1614
1615 if (options->auth_iv_param && (options->auth_iv_random_size != -1))
1616 printf("Auth IV already parsed, ignoring size of random IV\n");
1617
1618 if (options->aad_param && (options->aad_random_size != -1))
1619 printf("AAD already parsed, ignoring size of random AAD\n");
1620
1621 printf("\nCrypto chain: ");
1622 switch (options->xform_chain) {
1623 case L2FWD_CRYPTO_AEAD:
1624 printf("Input --> %s --> Output\n", string_aead_op);
1625 display_aead_info(options);
1626 break;
1627 case L2FWD_CRYPTO_CIPHER_HASH:
1628 printf("Input --> %s --> %s --> Output\n",
1629 string_cipher_op, string_auth_op);
1630 display_cipher_info(options);
1631 display_auth_info(options);
1632 break;
1633 case L2FWD_CRYPTO_HASH_CIPHER:
1634 printf("Input --> %s --> %s --> Output\n",
1635 string_auth_op, string_cipher_op);
1636 display_cipher_info(options);
1637 display_auth_info(options);
1638 break;
1639 case L2FWD_CRYPTO_HASH_ONLY:
1640 printf("Input --> %s --> Output\n", string_auth_op);
1641 display_auth_info(options);
1642 break;
1643 case L2FWD_CRYPTO_CIPHER_ONLY:
1644 printf("Input --> %s --> Output\n", string_cipher_op);
1645 display_cipher_info(options);
1646 break;
1647 }
1648 }
1649
1650 /* Parse the argument given in the command line of the application */
1651 static int
l2fwd_crypto_parse_args(struct l2fwd_crypto_options * options,int argc,char ** argv)1652 l2fwd_crypto_parse_args(struct l2fwd_crypto_options *options,
1653 int argc, char **argv)
1654 {
1655 int opt, retval, option_index;
1656 char **argvopt = argv, *prgname = argv[0];
1657
1658 static struct option lgopts[] = {
1659 { "sessionless", no_argument, 0, 0 },
1660
1661 { "cdev_type", required_argument, 0, 0 },
1662 { "chain", required_argument, 0, 0 },
1663
1664 { "cipher_algo", required_argument, 0, 0 },
1665 { "cipher_op", required_argument, 0, 0 },
1666 { "cipher_key", required_argument, 0, 0 },
1667 { "cipher_key_random_size", required_argument, 0, 0 },
1668 { "cipher_iv", required_argument, 0, 0 },
1669 { "cipher_iv_random_size", required_argument, 0, 0 },
1670 { "cipher_dataunit_len", required_argument, 0, 0},
1671
1672 { "auth_algo", required_argument, 0, 0 },
1673 { "auth_op", required_argument, 0, 0 },
1674 { "auth_key", required_argument, 0, 0 },
1675 { "auth_key_random_size", required_argument, 0, 0 },
1676 { "auth_iv", required_argument, 0, 0 },
1677 { "auth_iv_random_size", required_argument, 0, 0 },
1678
1679 { "aead_algo", required_argument, 0, 0 },
1680 { "aead_op", required_argument, 0, 0 },
1681 { "aead_key", required_argument, 0, 0 },
1682 { "aead_key_random_size", required_argument, 0, 0 },
1683 { "aead_iv", required_argument, 0, 0 },
1684 { "aead_iv_random_size", required_argument, 0, 0 },
1685
1686 { "aad", required_argument, 0, 0 },
1687 { "aad_random_size", required_argument, 0, 0 },
1688
1689 { "digest_size", required_argument, 0, 0 },
1690
1691 { "sessionless", no_argument, 0, 0 },
1692 { "cryptodev_mask", required_argument, 0, 0},
1693
1694 { "mac-updating", no_argument, 0, 0},
1695 { "no-mac-updating", no_argument, 0, 0},
1696
1697 { NULL, 0, 0, 0 }
1698 };
1699
1700 l2fwd_crypto_default_options(options);
1701
1702 while ((opt = getopt_long(argc, argvopt, "p:q:sT:", lgopts,
1703 &option_index)) != EOF) {
1704 switch (opt) {
1705 /* long options */
1706 case 0:
1707 retval = l2fwd_crypto_parse_args_long_options(options,
1708 lgopts, option_index);
1709 if (retval < 0) {
1710 l2fwd_crypto_usage(prgname);
1711 return -1;
1712 }
1713 break;
1714
1715 /* portmask */
1716 case 'p':
1717 retval = l2fwd_crypto_parse_portmask(options, optarg);
1718 if (retval < 0) {
1719 l2fwd_crypto_usage(prgname);
1720 return -1;
1721 }
1722 break;
1723
1724 /* nqueue */
1725 case 'q':
1726 retval = l2fwd_crypto_parse_nqueue(options, optarg);
1727 if (retval < 0) {
1728 l2fwd_crypto_usage(prgname);
1729 return -1;
1730 }
1731 break;
1732
1733 /* single */
1734 case 's':
1735 options->single_lcore = 1;
1736
1737 break;
1738
1739 /* timer period */
1740 case 'T':
1741 retval = l2fwd_crypto_parse_timer_period(options,
1742 optarg);
1743 if (retval < 0) {
1744 l2fwd_crypto_usage(prgname);
1745 return -1;
1746 }
1747 break;
1748
1749 default:
1750 l2fwd_crypto_usage(prgname);
1751 return -1;
1752 }
1753 }
1754
1755
1756 if (optind >= 0)
1757 argv[optind-1] = prgname;
1758
1759 retval = optind-1;
1760 optind = 1; /* reset getopt lib */
1761
1762 return retval;
1763 }
1764
1765 /* Check the link status of all ports in up to 9s, and print them finally */
1766 static void
check_all_ports_link_status(uint32_t port_mask)1767 check_all_ports_link_status(uint32_t port_mask)
1768 {
1769 #define CHECK_INTERVAL 100 /* 100ms */
1770 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
1771 uint16_t portid;
1772 uint8_t count, all_ports_up, print_flag = 0;
1773 struct rte_eth_link link;
1774 int ret;
1775 char link_status_text[RTE_ETH_LINK_MAX_STR_LEN];
1776
1777 printf("\nChecking link status");
1778 fflush(stdout);
1779 for (count = 0; count <= MAX_CHECK_TIME; count++) {
1780 all_ports_up = 1;
1781 RTE_ETH_FOREACH_DEV(portid) {
1782 if ((port_mask & (1 << portid)) == 0)
1783 continue;
1784 memset(&link, 0, sizeof(link));
1785 ret = rte_eth_link_get_nowait(portid, &link);
1786 if (ret < 0) {
1787 all_ports_up = 0;
1788 if (print_flag == 1)
1789 printf("Port %u link get failed: %s\n",
1790 portid, rte_strerror(-ret));
1791 continue;
1792 }
1793 /* print link status if flag set */
1794 if (print_flag == 1) {
1795 rte_eth_link_to_str(link_status_text,
1796 sizeof(link_status_text), &link);
1797 printf("Port %d %s\n", portid,
1798 link_status_text);
1799 continue;
1800 }
1801 /* clear all_ports_up flag if any link down */
1802 if (link.link_status == RTE_ETH_LINK_DOWN) {
1803 all_ports_up = 0;
1804 break;
1805 }
1806 }
1807 /* after finally printing all link status, get out */
1808 if (print_flag == 1)
1809 break;
1810
1811 if (all_ports_up == 0) {
1812 printf(".");
1813 fflush(stdout);
1814 rte_delay_ms(CHECK_INTERVAL);
1815 }
1816
1817 /* set the print_flag if all ports up or timeout */
1818 if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
1819 print_flag = 1;
1820 printf("done\n");
1821 }
1822 }
1823 }
1824
1825 /* Check if device has to be HW/SW or any */
1826 static int
check_type(const struct l2fwd_crypto_options * options,const struct rte_cryptodev_info * dev_info)1827 check_type(const struct l2fwd_crypto_options *options,
1828 const struct rte_cryptodev_info *dev_info)
1829 {
1830 if (options->type == CDEV_TYPE_HW &&
1831 (dev_info->feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED))
1832 return 0;
1833 if (options->type == CDEV_TYPE_SW &&
1834 !(dev_info->feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED))
1835 return 0;
1836 if (options->type == CDEV_TYPE_ANY)
1837 return 0;
1838
1839 return -1;
1840 }
1841
1842 static const struct rte_cryptodev_capabilities *
check_device_support_cipher_algo(const struct l2fwd_crypto_options * options,const struct rte_cryptodev_info * dev_info,uint8_t cdev_id)1843 check_device_support_cipher_algo(const struct l2fwd_crypto_options *options,
1844 const struct rte_cryptodev_info *dev_info,
1845 uint8_t cdev_id)
1846 {
1847 unsigned int i = 0;
1848 const struct rte_cryptodev_capabilities *cap = &dev_info->capabilities[0];
1849 enum rte_crypto_cipher_algorithm cap_cipher_algo;
1850 enum rte_crypto_cipher_algorithm opt_cipher_algo =
1851 options->cipher_xform.cipher.algo;
1852
1853 while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1854 cap_cipher_algo = cap->sym.cipher.algo;
1855 if (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
1856 if (cap_cipher_algo == opt_cipher_algo) {
1857 if (check_type(options, dev_info) == 0)
1858 break;
1859 }
1860 }
1861 cap = &dev_info->capabilities[++i];
1862 }
1863
1864 if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1865 printf("Algorithm %s not supported by cryptodev %u"
1866 " or device not of preferred type (%s)\n",
1867 rte_cryptodev_get_cipher_algo_string(opt_cipher_algo),
1868 cdev_id,
1869 options->string_type);
1870 return NULL;
1871 }
1872
1873 return cap;
1874 }
1875
1876 static const struct rte_cryptodev_capabilities *
check_device_support_auth_algo(const struct l2fwd_crypto_options * options,const struct rte_cryptodev_info * dev_info,uint8_t cdev_id)1877 check_device_support_auth_algo(const struct l2fwd_crypto_options *options,
1878 const struct rte_cryptodev_info *dev_info,
1879 uint8_t cdev_id)
1880 {
1881 unsigned int i = 0;
1882 const struct rte_cryptodev_capabilities *cap = &dev_info->capabilities[0];
1883 enum rte_crypto_auth_algorithm cap_auth_algo;
1884 enum rte_crypto_auth_algorithm opt_auth_algo =
1885 options->auth_xform.auth.algo;
1886
1887 while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1888 cap_auth_algo = cap->sym.auth.algo;
1889 if (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AUTH) {
1890 if (cap_auth_algo == opt_auth_algo) {
1891 if (check_type(options, dev_info) == 0)
1892 break;
1893 }
1894 }
1895 cap = &dev_info->capabilities[++i];
1896 }
1897
1898 if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1899 printf("Algorithm %s not supported by cryptodev %u"
1900 " or device not of preferred type (%s)\n",
1901 rte_cryptodev_get_auth_algo_string(opt_auth_algo),
1902 cdev_id,
1903 options->string_type);
1904 return NULL;
1905 }
1906
1907 return cap;
1908 }
1909
1910 static const struct rte_cryptodev_capabilities *
check_device_support_aead_algo(const struct l2fwd_crypto_options * options,const struct rte_cryptodev_info * dev_info,uint8_t cdev_id)1911 check_device_support_aead_algo(const struct l2fwd_crypto_options *options,
1912 const struct rte_cryptodev_info *dev_info,
1913 uint8_t cdev_id)
1914 {
1915 unsigned int i = 0;
1916 const struct rte_cryptodev_capabilities *cap = &dev_info->capabilities[0];
1917 enum rte_crypto_aead_algorithm cap_aead_algo;
1918 enum rte_crypto_aead_algorithm opt_aead_algo =
1919 options->aead_xform.aead.algo;
1920
1921 while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1922 cap_aead_algo = cap->sym.aead.algo;
1923 if (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AEAD) {
1924 if (cap_aead_algo == opt_aead_algo) {
1925 if (check_type(options, dev_info) == 0)
1926 break;
1927 }
1928 }
1929 cap = &dev_info->capabilities[++i];
1930 }
1931
1932 if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1933 printf("Algorithm %s not supported by cryptodev %u"
1934 " or device not of preferred type (%s)\n",
1935 rte_cryptodev_get_aead_algo_string(opt_aead_algo),
1936 cdev_id,
1937 options->string_type);
1938 return NULL;
1939 }
1940
1941 return cap;
1942 }
1943
1944 /* Check if the device is enabled by cryptodev_mask */
1945 static int
check_cryptodev_mask(struct l2fwd_crypto_options * options,uint8_t cdev_id)1946 check_cryptodev_mask(struct l2fwd_crypto_options *options,
1947 uint8_t cdev_id)
1948 {
1949 if (options->cryptodev_mask & (1 << cdev_id))
1950 return 0;
1951
1952 return -1;
1953 }
1954
1955 static inline int
check_supported_size(uint16_t length,uint16_t min,uint16_t max,uint16_t increment)1956 check_supported_size(uint16_t length, uint16_t min, uint16_t max,
1957 uint16_t increment)
1958 {
1959 uint16_t supp_size;
1960
1961 /* Single value */
1962 if (increment == 0) {
1963 if (length == min)
1964 return 0;
1965 else
1966 return -1;
1967 }
1968
1969 /* Range of values */
1970 for (supp_size = min; supp_size <= max; supp_size += increment) {
1971 if (length == supp_size)
1972 return 0;
1973 }
1974
1975 return -1;
1976 }
1977
1978 static int
check_iv_param(const struct rte_crypto_param_range * iv_range_size,unsigned int iv_param,int iv_random_size,uint16_t iv_length)1979 check_iv_param(const struct rte_crypto_param_range *iv_range_size,
1980 unsigned int iv_param, int iv_random_size,
1981 uint16_t iv_length)
1982 {
1983 /*
1984 * Check if length of provided IV is supported
1985 * by the algorithm chosen.
1986 */
1987 if (iv_param) {
1988 if (check_supported_size(iv_length,
1989 iv_range_size->min,
1990 iv_range_size->max,
1991 iv_range_size->increment)
1992 != 0)
1993 return -1;
1994 /*
1995 * Check if length of IV to be randomly generated
1996 * is supported by the algorithm chosen.
1997 */
1998 } else if (iv_random_size != -1) {
1999 if (check_supported_size(iv_random_size,
2000 iv_range_size->min,
2001 iv_range_size->max,
2002 iv_range_size->increment)
2003 != 0)
2004 return -1;
2005 }
2006
2007 return 0;
2008 }
2009
2010 static int
check_capabilities(struct l2fwd_crypto_options * options,uint8_t cdev_id)2011 check_capabilities(struct l2fwd_crypto_options *options, uint8_t cdev_id)
2012 {
2013 struct rte_cryptodev_info dev_info;
2014 const struct rte_cryptodev_capabilities *cap;
2015
2016 rte_cryptodev_info_get(cdev_id, &dev_info);
2017
2018 /* Set AEAD parameters */
2019 if (options->xform_chain == L2FWD_CRYPTO_AEAD) {
2020 /* Check if device supports AEAD algo */
2021 cap = check_device_support_aead_algo(options, &dev_info,
2022 cdev_id);
2023 if (cap == NULL)
2024 return -1;
2025
2026 if (check_iv_param(&cap->sym.aead.iv_size,
2027 options->aead_iv_param,
2028 options->aead_iv_random_size,
2029 options->aead_iv.length) != 0) {
2030 RTE_LOG(DEBUG, USER1,
2031 "Device %u does not support IV length\n",
2032 cdev_id);
2033 return -1;
2034 }
2035
2036 /*
2037 * Check if length of provided AEAD key is supported
2038 * by the algorithm chosen.
2039 */
2040 if (options->aead_key_param) {
2041 if (check_supported_size(
2042 options->aead_xform.aead.key.length,
2043 cap->sym.aead.key_size.min,
2044 cap->sym.aead.key_size.max,
2045 cap->sym.aead.key_size.increment)
2046 != 0) {
2047 RTE_LOG(DEBUG, USER1,
2048 "Device %u does not support "
2049 "AEAD key length\n",
2050 cdev_id);
2051 return -1;
2052 }
2053 /*
2054 * Check if length of the aead key to be randomly generated
2055 * is supported by the algorithm chosen.
2056 */
2057 } else if (options->aead_key_random_size != -1) {
2058 if (check_supported_size(options->aead_key_random_size,
2059 cap->sym.aead.key_size.min,
2060 cap->sym.aead.key_size.max,
2061 cap->sym.aead.key_size.increment)
2062 != 0) {
2063 RTE_LOG(DEBUG, USER1,
2064 "Device %u does not support "
2065 "AEAD key length\n",
2066 cdev_id);
2067 return -1;
2068 }
2069 }
2070
2071
2072 /*
2073 * Check if length of provided AAD is supported
2074 * by the algorithm chosen.
2075 */
2076 if (options->aad_param) {
2077 if (check_supported_size(options->aad.length,
2078 cap->sym.aead.aad_size.min,
2079 cap->sym.aead.aad_size.max,
2080 cap->sym.aead.aad_size.increment)
2081 != 0) {
2082 RTE_LOG(DEBUG, USER1,
2083 "Device %u does not support "
2084 "AAD length\n",
2085 cdev_id);
2086 return -1;
2087 }
2088 /*
2089 * Check if length of AAD to be randomly generated
2090 * is supported by the algorithm chosen.
2091 */
2092 } else if (options->aad_random_size != -1) {
2093 if (check_supported_size(options->aad_random_size,
2094 cap->sym.aead.aad_size.min,
2095 cap->sym.aead.aad_size.max,
2096 cap->sym.aead.aad_size.increment)
2097 != 0) {
2098 RTE_LOG(DEBUG, USER1,
2099 "Device %u does not support "
2100 "AAD length\n",
2101 cdev_id);
2102 return -1;
2103 }
2104 }
2105
2106 /* Check if digest size is supported by the algorithm. */
2107 if (options->digest_size != -1) {
2108 if (check_supported_size(options->digest_size,
2109 cap->sym.aead.digest_size.min,
2110 cap->sym.aead.digest_size.max,
2111 cap->sym.aead.digest_size.increment)
2112 != 0) {
2113 RTE_LOG(DEBUG, USER1,
2114 "Device %u does not support "
2115 "digest length\n",
2116 cdev_id);
2117 return -1;
2118 }
2119 }
2120 }
2121
2122 /* Set cipher parameters */
2123 if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
2124 options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
2125 options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
2126
2127 /* Check if device supports cipher algo. 8< */
2128 cap = check_device_support_cipher_algo(options, &dev_info,
2129 cdev_id);
2130 if (cap == NULL)
2131 return -1;
2132
2133 if (check_iv_param(&cap->sym.cipher.iv_size,
2134 options->cipher_iv_param,
2135 options->cipher_iv_random_size,
2136 options->cipher_iv.length) != 0) {
2137 RTE_LOG(DEBUG, USER1,
2138 "Device %u does not support IV length\n",
2139 cdev_id);
2140 return -1;
2141 }
2142 /* >8 End of check if device supports cipher algo. */
2143
2144 /* Check if capable cipher is supported. 8< */
2145
2146 /*
2147 * Check if length of provided cipher key is supported
2148 * by the algorithm chosen.
2149 */
2150 if (options->ckey_param) {
2151 if (check_supported_size(
2152 options->cipher_xform.cipher.key.length,
2153 cap->sym.cipher.key_size.min,
2154 cap->sym.cipher.key_size.max,
2155 cap->sym.cipher.key_size.increment)
2156 != 0) {
2157 if (dev_info.feature_flags &
2158 RTE_CRYPTODEV_FF_CIPHER_WRAPPED_KEY) {
2159 RTE_LOG(DEBUG, USER1,
2160 "Key length does not match the device "
2161 "%u capability. Key may be wrapped\n",
2162 cdev_id);
2163 } else {
2164 RTE_LOG(DEBUG, USER1,
2165 "Key length does not match the device "
2166 "%u capability\n",
2167 cdev_id);
2168 return -1;
2169 }
2170 }
2171
2172 /*
2173 * Check if length of the cipher key to be randomly generated
2174 * is supported by the algorithm chosen.
2175 */
2176 } else if (options->ckey_random_size != -1) {
2177 if (check_supported_size(options->ckey_random_size,
2178 cap->sym.cipher.key_size.min,
2179 cap->sym.cipher.key_size.max,
2180 cap->sym.cipher.key_size.increment)
2181 != 0) {
2182 RTE_LOG(DEBUG, USER1,
2183 "Device %u does not support cipher "
2184 "key length\n",
2185 cdev_id);
2186 return -1;
2187 }
2188 }
2189
2190 if (options->cipher_xform.cipher.dataunit_len > 0) {
2191 if (!(dev_info.feature_flags &
2192 RTE_CRYPTODEV_FF_CIPHER_MULTIPLE_DATA_UNITS)) {
2193 RTE_LOG(DEBUG, USER1,
2194 "Device %u does not support "
2195 "cipher multiple data units\n",
2196 cdev_id);
2197 return -1;
2198 }
2199 if (cap->sym.cipher.dataunit_set != 0) {
2200 int ret = 0;
2201
2202 switch (options->cipher_xform.cipher.dataunit_len) {
2203 case 512:
2204 if (!(cap->sym.cipher.dataunit_set &
2205 RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_512_BYTES))
2206 ret = -1;
2207 break;
2208 case 4096:
2209 if (!(cap->sym.cipher.dataunit_set &
2210 RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_4096_BYTES))
2211 ret = -1;
2212 break;
2213 case 1048576:
2214 if (!(cap->sym.cipher.dataunit_set &
2215 RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_1_MEGABYTES))
2216 ret = -1;
2217 break;
2218 default:
2219 ret = -1;
2220 }
2221 if (ret == -1) {
2222 RTE_LOG(DEBUG, USER1,
2223 "Device %u does not support "
2224 "data-unit length %u\n",
2225 cdev_id,
2226 options->cipher_xform.cipher.dataunit_len);
2227 return -1;
2228 }
2229 }
2230 }
2231 /* >8 End of checking if cipher is supported. */
2232 }
2233
2234 /* Set auth parameters */
2235 if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
2236 options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
2237 options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) {
2238 /* Check if device supports auth algo */
2239 cap = check_device_support_auth_algo(options, &dev_info,
2240 cdev_id);
2241 if (cap == NULL)
2242 return -1;
2243
2244 if (check_iv_param(&cap->sym.auth.iv_size,
2245 options->auth_iv_param,
2246 options->auth_iv_random_size,
2247 options->auth_iv.length) != 0) {
2248 RTE_LOG(DEBUG, USER1,
2249 "Device %u does not support IV length\n",
2250 cdev_id);
2251 return -1;
2252 }
2253 /*
2254 * Check if length of provided auth key is supported
2255 * by the algorithm chosen.
2256 */
2257 if (options->akey_param) {
2258 if (check_supported_size(
2259 options->auth_xform.auth.key.length,
2260 cap->sym.auth.key_size.min,
2261 cap->sym.auth.key_size.max,
2262 cap->sym.auth.key_size.increment)
2263 != 0) {
2264 RTE_LOG(DEBUG, USER1,
2265 "Device %u does not support auth "
2266 "key length\n",
2267 cdev_id);
2268 return -1;
2269 }
2270 /*
2271 * Check if length of the auth key to be randomly generated
2272 * is supported by the algorithm chosen.
2273 */
2274 } else if (options->akey_random_size != -1) {
2275 if (check_supported_size(options->akey_random_size,
2276 cap->sym.auth.key_size.min,
2277 cap->sym.auth.key_size.max,
2278 cap->sym.auth.key_size.increment)
2279 != 0) {
2280 RTE_LOG(DEBUG, USER1,
2281 "Device %u does not support auth "
2282 "key length\n",
2283 cdev_id);
2284 return -1;
2285 }
2286 }
2287
2288 /* Check if digest size is supported by the algorithm. */
2289 if (options->digest_size != -1) {
2290 if (check_supported_size(options->digest_size,
2291 cap->sym.auth.digest_size.min,
2292 cap->sym.auth.digest_size.max,
2293 cap->sym.auth.digest_size.increment)
2294 != 0) {
2295 RTE_LOG(DEBUG, USER1,
2296 "Device %u does not support "
2297 "digest length\n",
2298 cdev_id);
2299 return -1;
2300 }
2301 }
2302 }
2303
2304 return 0;
2305 }
2306
2307 static int
initialize_cryptodevs(struct l2fwd_crypto_options * options,unsigned nb_ports,uint8_t * enabled_cdevs)2308 initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports,
2309 uint8_t *enabled_cdevs)
2310 {
2311 uint8_t cdev_id, cdev_count, enabled_cdev_count = 0;
2312 const struct rte_cryptodev_capabilities *cap;
2313 unsigned int sess_sz, max_sess_sz = 0;
2314 uint32_t sessions_needed = 0;
2315 int retval;
2316
2317 cdev_count = rte_cryptodev_count();
2318 if (cdev_count == 0) {
2319 printf("No crypto devices available\n");
2320 return -1;
2321 }
2322
2323 for (cdev_id = 0; cdev_id < cdev_count && enabled_cdev_count < nb_ports;
2324 cdev_id++) {
2325 if (check_cryptodev_mask(options, cdev_id) < 0)
2326 continue;
2327
2328 if (check_capabilities(options, cdev_id) < 0)
2329 continue;
2330
2331 sess_sz = rte_cryptodev_sym_get_private_session_size(cdev_id);
2332 if (sess_sz > max_sess_sz)
2333 max_sess_sz = sess_sz;
2334
2335 l2fwd_enabled_crypto_mask |= (((uint64_t)1) << cdev_id);
2336
2337 enabled_cdevs[cdev_id] = 1;
2338 enabled_cdev_count++;
2339 }
2340
2341 for (cdev_id = 0; cdev_id < cdev_count; cdev_id++) {
2342 struct rte_cryptodev_qp_conf qp_conf;
2343 struct rte_cryptodev_info dev_info;
2344
2345 if (enabled_cdevs[cdev_id] == 0)
2346 continue;
2347
2348 if (check_cryptodev_mask(options, cdev_id) < 0)
2349 continue;
2350
2351 if (check_capabilities(options, cdev_id) < 0)
2352 continue;
2353
2354 retval = rte_cryptodev_socket_id(cdev_id);
2355
2356 if (retval < 0) {
2357 printf("Invalid crypto device id used\n");
2358 return -1;
2359 }
2360
2361 uint8_t socket_id = (uint8_t) retval;
2362
2363 struct rte_cryptodev_config conf = {
2364 .nb_queue_pairs = 1,
2365 .socket_id = socket_id,
2366 .ff_disable = RTE_CRYPTODEV_FF_SECURITY,
2367 };
2368
2369 rte_cryptodev_info_get(cdev_id, &dev_info);
2370
2371 if (!strcmp(dev_info.driver_name, "crypto_scheduler")) {
2372 #ifdef RTE_CRYPTO_SCHEDULER
2373 /* scheduler session header + 1 session per worker */
2374 uint32_t nb_workers = 1 +
2375 rte_cryptodev_scheduler_workers_get(cdev_id,
2376 NULL);
2377
2378 sessions_needed = enabled_cdev_count * nb_workers;
2379 #endif
2380 } else
2381 sessions_needed = enabled_cdev_count;
2382
2383 if (session_pool_socket[socket_id].sess_mp == NULL) {
2384 char mp_name[RTE_MEMPOOL_NAMESIZE];
2385 snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
2386 "sess_mp_%u", socket_id);
2387
2388 session_pool_socket[socket_id].sess_mp =
2389 rte_cryptodev_sym_session_pool_create(
2390 mp_name, sessions_needed, max_sess_sz,
2391 0, 0, socket_id);
2392 if (session_pool_socket[socket_id].sess_mp == NULL) {
2393 printf("Cannot create pool on socket %d\n",
2394 socket_id);
2395 return -ENOMEM;
2396 }
2397
2398 printf("Allocated pool \"%s\" on socket %d\n",
2399 mp_name, socket_id);
2400 }
2401
2402 /* Set AEAD parameters */
2403 if (options->xform_chain == L2FWD_CRYPTO_AEAD) {
2404 cap = check_device_support_aead_algo(options, &dev_info,
2405 cdev_id);
2406
2407 options->block_size = cap->sym.aead.block_size;
2408
2409 /* Set IV if not provided from command line */
2410 if (options->aead_iv_param == 0) {
2411 if (options->aead_iv_random_size != -1)
2412 options->aead_iv.length =
2413 options->aead_iv_random_size;
2414 /* No size provided, use minimum size. */
2415 else
2416 options->aead_iv.length =
2417 cap->sym.aead.iv_size.min;
2418 }
2419
2420 /* Set key if not provided from command line */
2421 if (options->aead_key_param == 0) {
2422 if (options->aead_key_random_size != -1)
2423 options->aead_xform.aead.key.length =
2424 options->aead_key_random_size;
2425 /* No size provided, use minimum size. */
2426 else
2427 options->aead_xform.aead.key.length =
2428 cap->sym.aead.key_size.min;
2429
2430 generate_random_key(options->aead_key,
2431 options->aead_xform.aead.key.length);
2432 }
2433
2434 /* Set AAD if not provided from command line */
2435 if (options->aad_param == 0) {
2436 if (options->aad_random_size != -1)
2437 options->aad.length =
2438 options->aad_random_size;
2439 /* No size provided, use minimum size. */
2440 else
2441 options->aad.length =
2442 cap->sym.auth.aad_size.min;
2443 }
2444
2445 options->aead_xform.aead.aad_length =
2446 options->aad.length;
2447
2448 /* Set digest size if not provided from command line */
2449 if (options->digest_size != -1)
2450 options->aead_xform.aead.digest_length =
2451 options->digest_size;
2452 /* No size provided, use minimum size. */
2453 else
2454 options->aead_xform.aead.digest_length =
2455 cap->sym.aead.digest_size.min;
2456 }
2457
2458 /* Set cipher parameters */
2459 if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
2460 options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
2461 options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
2462 cap = check_device_support_cipher_algo(options, &dev_info,
2463 cdev_id);
2464 options->block_size = cap->sym.cipher.block_size;
2465
2466 /* Set IV if not provided from command line */
2467 if (options->cipher_iv_param == 0) {
2468 if (options->cipher_iv_random_size != -1)
2469 options->cipher_iv.length =
2470 options->cipher_iv_random_size;
2471 /* No size provided, use minimum size. */
2472 else
2473 options->cipher_iv.length =
2474 cap->sym.cipher.iv_size.min;
2475 }
2476
2477 /* Set key if not provided from command line */
2478 if (options->ckey_param == 0) {
2479 if (options->ckey_random_size != -1)
2480 options->cipher_xform.cipher.key.length =
2481 options->ckey_random_size;
2482 /* No size provided, use minimum size. */
2483 else
2484 options->cipher_xform.cipher.key.length =
2485 cap->sym.cipher.key_size.min;
2486
2487 generate_random_key(options->cipher_key,
2488 options->cipher_xform.cipher.key.length);
2489 }
2490 }
2491
2492 /* Set auth parameters */
2493 if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
2494 options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
2495 options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) {
2496 cap = check_device_support_auth_algo(options, &dev_info,
2497 cdev_id);
2498
2499 /* Set IV if not provided from command line */
2500 if (options->auth_iv_param == 0) {
2501 if (options->auth_iv_random_size != -1)
2502 options->auth_iv.length =
2503 options->auth_iv_random_size;
2504 /* No size provided, use minimum size. */
2505 else
2506 options->auth_iv.length =
2507 cap->sym.auth.iv_size.min;
2508 }
2509
2510 /* Set key if not provided from command line */
2511 if (options->akey_param == 0) {
2512 if (options->akey_random_size != -1)
2513 options->auth_xform.auth.key.length =
2514 options->akey_random_size;
2515 /* No size provided, use minimum size. */
2516 else
2517 options->auth_xform.auth.key.length =
2518 cap->sym.auth.key_size.min;
2519
2520 generate_random_key(options->auth_key,
2521 options->auth_xform.auth.key.length);
2522 }
2523
2524 /* Set digest size if not provided from command line */
2525 if (options->digest_size != -1)
2526 options->auth_xform.auth.digest_length =
2527 options->digest_size;
2528 /* No size provided, use minimum size. */
2529 else
2530 options->auth_xform.auth.digest_length =
2531 cap->sym.auth.digest_size.min;
2532 }
2533
2534 retval = rte_cryptodev_configure(cdev_id, &conf);
2535 if (retval < 0) {
2536 printf("Failed to configure cryptodev %u", cdev_id);
2537 return -1;
2538 }
2539
2540 qp_conf.nb_descriptors = 2048;
2541 qp_conf.mp_session = session_pool_socket[socket_id].sess_mp;
2542
2543 retval = rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
2544 socket_id);
2545 if (retval < 0) {
2546 printf("Failed to setup queue pair %u on cryptodev %u",
2547 0, cdev_id);
2548 return -1;
2549 }
2550
2551 retval = rte_cryptodev_start(cdev_id);
2552 if (retval < 0) {
2553 printf("Failed to start device %u: error %d\n",
2554 cdev_id, retval);
2555 return -1;
2556 }
2557 }
2558
2559 return enabled_cdev_count;
2560 }
2561
2562 static int
initialize_ports(struct l2fwd_crypto_options * options)2563 initialize_ports(struct l2fwd_crypto_options *options)
2564 {
2565 uint16_t last_portid = 0, portid;
2566 unsigned enabled_portcount = 0;
2567 unsigned nb_ports = rte_eth_dev_count_avail();
2568
2569 if (nb_ports == 0) {
2570 printf("No Ethernet ports - bye\n");
2571 return -1;
2572 }
2573
2574 /* Reset l2fwd_dst_ports */
2575 for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
2576 l2fwd_dst_ports[portid] = 0;
2577
2578 RTE_ETH_FOREACH_DEV(portid) {
2579 int retval;
2580 struct rte_eth_dev_info dev_info;
2581 struct rte_eth_rxconf rxq_conf;
2582 struct rte_eth_txconf txq_conf;
2583 struct rte_eth_conf local_port_conf = port_conf;
2584
2585 /* Skip ports that are not enabled */
2586 if ((options->portmask & (1 << portid)) == 0)
2587 continue;
2588
2589 /* init port */
2590 printf("Initializing port %u... ", portid);
2591 fflush(stdout);
2592
2593 retval = rte_eth_dev_info_get(portid, &dev_info);
2594 if (retval != 0) {
2595 printf("Error during getting device (port %u) info: %s\n",
2596 portid, strerror(-retval));
2597 return retval;
2598 }
2599
2600 if (dev_info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE)
2601 local_port_conf.txmode.offloads |=
2602 RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE;
2603 retval = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
2604 if (retval < 0) {
2605 printf("Cannot configure device: err=%d, port=%u\n",
2606 retval, portid);
2607 return -1;
2608 }
2609
2610 retval = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
2611 &nb_txd);
2612 if (retval < 0) {
2613 printf("Cannot adjust number of descriptors: err=%d, port=%u\n",
2614 retval, portid);
2615 return -1;
2616 }
2617
2618 /* init one RX queue */
2619 fflush(stdout);
2620 rxq_conf = dev_info.default_rxconf;
2621 rxq_conf.offloads = local_port_conf.rxmode.offloads;
2622 retval = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
2623 rte_eth_dev_socket_id(portid),
2624 &rxq_conf, l2fwd_pktmbuf_pool);
2625 if (retval < 0) {
2626 printf("rte_eth_rx_queue_setup:err=%d, port=%u\n",
2627 retval, portid);
2628 return -1;
2629 }
2630
2631 /* init one TX queue on each port */
2632 fflush(stdout);
2633 txq_conf = dev_info.default_txconf;
2634 txq_conf.offloads = local_port_conf.txmode.offloads;
2635 retval = rte_eth_tx_queue_setup(portid, 0, nb_txd,
2636 rte_eth_dev_socket_id(portid),
2637 &txq_conf);
2638 if (retval < 0) {
2639 printf("rte_eth_tx_queue_setup:err=%d, port=%u\n",
2640 retval, portid);
2641
2642 return -1;
2643 }
2644
2645 /* Start device */
2646 retval = rte_eth_dev_start(portid);
2647 if (retval < 0) {
2648 printf("rte_eth_dev_start:err=%d, port=%u\n",
2649 retval, portid);
2650 return -1;
2651 }
2652
2653 retval = rte_eth_promiscuous_enable(portid);
2654 if (retval != 0) {
2655 printf("rte_eth_promiscuous_enable:err=%s, port=%u\n",
2656 rte_strerror(-retval), portid);
2657 return -1;
2658 }
2659
2660 retval = rte_eth_macaddr_get(portid,
2661 &l2fwd_ports_eth_addr[portid]);
2662 if (retval < 0) {
2663 printf("rte_eth_macaddr_get :err=%d, port=%u\n",
2664 retval, portid);
2665 return -1;
2666 }
2667
2668 printf("Port %u, MAC address: " RTE_ETHER_ADDR_PRT_FMT "\n\n",
2669 portid,
2670 RTE_ETHER_ADDR_BYTES(&l2fwd_ports_eth_addr[portid]));
2671
2672 /* initialize port stats */
2673 memset(&port_statistics, 0, sizeof(port_statistics));
2674
2675 /* Setup port forwarding table */
2676 if (enabled_portcount % 2) {
2677 l2fwd_dst_ports[portid] = last_portid;
2678 l2fwd_dst_ports[last_portid] = portid;
2679 } else {
2680 last_portid = portid;
2681 }
2682
2683 l2fwd_enabled_port_mask |= (1ULL << portid);
2684 enabled_portcount++;
2685 }
2686
2687 if (enabled_portcount == 1) {
2688 l2fwd_dst_ports[last_portid] = last_portid;
2689 } else if (enabled_portcount % 2) {
2690 printf("odd number of ports in portmask- bye\n");
2691 return -1;
2692 }
2693
2694 check_all_ports_link_status(l2fwd_enabled_port_mask);
2695
2696 return enabled_portcount;
2697 }
2698
2699 static void
reserve_key_memory(struct l2fwd_crypto_options * options)2700 reserve_key_memory(struct l2fwd_crypto_options *options)
2701 {
2702 options->cipher_xform.cipher.key.data = options->cipher_key;
2703
2704 options->auth_xform.auth.key.data = options->auth_key;
2705
2706 options->aead_xform.aead.key.data = options->aead_key;
2707
2708 options->cipher_iv.data = rte_malloc("cipher iv", MAX_KEY_SIZE, 0);
2709 if (options->cipher_iv.data == NULL)
2710 rte_exit(EXIT_FAILURE, "Failed to allocate memory for cipher IV");
2711
2712 options->auth_iv.data = rte_malloc("auth iv", MAX_KEY_SIZE, 0);
2713 if (options->auth_iv.data == NULL)
2714 rte_exit(EXIT_FAILURE, "Failed to allocate memory for auth IV");
2715
2716 options->aead_iv.data = rte_malloc("aead_iv", MAX_KEY_SIZE, 0);
2717 if (options->aead_iv.data == NULL)
2718 rte_exit(EXIT_FAILURE, "Failed to allocate memory for AEAD iv");
2719
2720 options->aad.data = rte_malloc("aad", MAX_KEY_SIZE, 0);
2721 if (options->aad.data == NULL)
2722 rte_exit(EXIT_FAILURE, "Failed to allocate memory for AAD");
2723 options->aad.phys_addr = rte_malloc_virt2iova(options->aad.data);
2724 }
2725
2726 static void
raise_signal(int signum)2727 raise_signal(int signum)
2728 {
2729 if (signum == SIGINT || signum == SIGTERM)
2730 signal_received = true;
2731 }
2732
2733 int
main(int argc,char ** argv)2734 main(int argc, char **argv)
2735 {
2736 struct lcore_queue_conf *qconf = NULL;
2737 struct l2fwd_crypto_options options;
2738
2739 uint8_t nb_cryptodevs, cdev_id;
2740 uint16_t portid;
2741 unsigned lcore_id, rx_lcore_id = 0;
2742 int ret, enabled_cdevcount, enabled_portcount;
2743 uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = {0};
2744
2745 signal(SIGINT, raise_signal);
2746 signal(SIGTERM, raise_signal);
2747
2748 /* init EAL */
2749 ret = rte_eal_init(argc, argv);
2750 if (ret < 0)
2751 rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
2752 argc -= ret;
2753 argv += ret;
2754
2755 /* reserve memory for Cipher/Auth key and IV */
2756 reserve_key_memory(&options);
2757
2758 /* parse application arguments (after the EAL ones) */
2759 ret = l2fwd_crypto_parse_args(&options, argc, argv);
2760 if (ret < 0)
2761 rte_exit(EXIT_FAILURE, "Invalid L2FWD-CRYPTO arguments\n");
2762
2763 printf("MAC updating %s\n",
2764 options.mac_updating ? "enabled" : "disabled");
2765
2766 /* create the mbuf pool */
2767 l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 512,
2768 RTE_ALIGN(sizeof(struct rte_crypto_op),
2769 RTE_CACHE_LINE_SIZE),
2770 RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2771 if (l2fwd_pktmbuf_pool == NULL)
2772 rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
2773
2774 /* create crypto op pool */
2775 l2fwd_crypto_op_pool = rte_crypto_op_pool_create("crypto_op_pool",
2776 RTE_CRYPTO_OP_TYPE_SYMMETRIC, NB_MBUF, 128, MAXIMUM_IV_LENGTH,
2777 rte_socket_id());
2778 if (l2fwd_crypto_op_pool == NULL)
2779 rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n");
2780
2781 /* Enable Ethernet ports */
2782 enabled_portcount = initialize_ports(&options);
2783 if (enabled_portcount < 1)
2784 rte_exit(EXIT_FAILURE, "Failed to initialize Ethernet ports\n");
2785
2786 /* Initialize the port/queue configuration of each logical core */
2787 RTE_ETH_FOREACH_DEV(portid) {
2788
2789 /* skip ports that are not enabled */
2790 if ((options.portmask & (1 << portid)) == 0)
2791 continue;
2792
2793 if (options.single_lcore && qconf == NULL) {
2794 while (rte_lcore_is_enabled(rx_lcore_id) == 0) {
2795 rx_lcore_id++;
2796 if (rx_lcore_id >= RTE_MAX_LCORE)
2797 rte_exit(EXIT_FAILURE,
2798 "Not enough cores\n");
2799 }
2800 } else if (!options.single_lcore) {
2801 /* get the lcore_id for this port */
2802 while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
2803 lcore_queue_conf[rx_lcore_id].nb_rx_ports ==
2804 options.nb_ports_per_lcore) {
2805 rx_lcore_id++;
2806 if (rx_lcore_id >= RTE_MAX_LCORE)
2807 rte_exit(EXIT_FAILURE,
2808 "Not enough cores\n");
2809 }
2810 }
2811
2812 /* Assigned a new logical core in the loop above. */
2813 if (qconf != &lcore_queue_conf[rx_lcore_id])
2814 qconf = &lcore_queue_conf[rx_lcore_id];
2815
2816 qconf->rx_port_list[qconf->nb_rx_ports] = portid;
2817 qconf->nb_rx_ports++;
2818
2819 printf("Lcore %u: RX port %u\n", rx_lcore_id, portid);
2820 }
2821
2822 /* Enable Crypto devices */
2823 enabled_cdevcount = initialize_cryptodevs(&options, enabled_portcount,
2824 enabled_cdevs);
2825 if (enabled_cdevcount < 0)
2826 rte_exit(EXIT_FAILURE, "Failed to initialize crypto devices\n");
2827
2828 if (enabled_cdevcount < enabled_portcount)
2829 rte_exit(EXIT_FAILURE, "Number of capable crypto devices (%d) "
2830 "has to be more or equal to number of ports (%d)\n",
2831 enabled_cdevcount, enabled_portcount);
2832
2833 nb_cryptodevs = rte_cryptodev_count();
2834
2835 /* Initialize the port/cryptodev configuration of each logical core */
2836 for (rx_lcore_id = 0, qconf = NULL, cdev_id = 0;
2837 cdev_id < nb_cryptodevs && enabled_cdevcount;
2838 cdev_id++) {
2839 /* Crypto op not supported by crypto device */
2840 if (!enabled_cdevs[cdev_id])
2841 continue;
2842
2843 if (options.single_lcore && qconf == NULL) {
2844 while (rte_lcore_is_enabled(rx_lcore_id) == 0) {
2845 rx_lcore_id++;
2846 if (rx_lcore_id >= RTE_MAX_LCORE)
2847 rte_exit(EXIT_FAILURE,
2848 "Not enough cores\n");
2849 }
2850 } else if (!options.single_lcore) {
2851 /* get the lcore_id for this port */
2852 while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
2853 lcore_queue_conf[rx_lcore_id].nb_crypto_devs ==
2854 options.nb_ports_per_lcore) {
2855 rx_lcore_id++;
2856 if (rx_lcore_id >= RTE_MAX_LCORE)
2857 rte_exit(EXIT_FAILURE,
2858 "Not enough cores\n");
2859 }
2860 }
2861
2862 /* Assigned a new logical core in the loop above. */
2863 if (qconf != &lcore_queue_conf[rx_lcore_id])
2864 qconf = &lcore_queue_conf[rx_lcore_id];
2865
2866 qconf->cryptodev_list[qconf->nb_crypto_devs] = cdev_id;
2867 qconf->nb_crypto_devs++;
2868
2869 enabled_cdevcount--;
2870
2871 printf("Lcore %u: cryptodev %u\n", rx_lcore_id,
2872 (unsigned)cdev_id);
2873 }
2874
2875 /* launch per-lcore init on every lcore */
2876 rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, (void *)&options,
2877 CALL_MAIN);
2878 RTE_LCORE_FOREACH_WORKER(lcore_id) {
2879 if (rte_eal_wait_lcore(lcore_id) < 0)
2880 return -1;
2881 }
2882
2883 /* clean up the EAL */
2884 rte_eal_cleanup();
2885
2886 return 0;
2887 }
2888