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