xref: /dpdk/examples/l2fwd-crypto/main.c (revision 8dbc9bbfe3d08d563abe7a65af7262af67214cf6)
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 	for (byte_count = 0, token = strtok(input_arg, ":");
1092 			(byte_count < MAX_KEY_SIZE) && (token != NULL);
1093 			token = strtok(NULL, ":")) {
1094 
1095 		int number = (int)strtol(token, NULL, 16);
1096 
1097 		if (errno == EINVAL || errno == ERANGE || number > 0xFF)
1098 			return -1;
1099 
1100 		data[byte_count++] = (uint8_t)number;
1101 	}
1102 
1103 	return byte_count;
1104 }
1105 
1106 /** Parse size param*/
1107 static int
1108 parse_size(int *size, const char *q_arg)
1109 {
1110 	char *end = NULL;
1111 	unsigned long n;
1112 
1113 	/* parse hexadecimal string */
1114 	n = strtoul(q_arg, &end, 10);
1115 	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1116 		n = 0;
1117 
1118 	if (n == 0) {
1119 		printf("invalid size\n");
1120 		return -1;
1121 	}
1122 
1123 	*size = n;
1124 	return 0;
1125 }
1126 
1127 /** Parse crypto cipher operation command line argument */
1128 static int
1129 parse_auth_algo(enum rte_crypto_auth_algorithm *algo, char *optarg)
1130 {
1131 	if (rte_cryptodev_get_auth_algo_enum(algo, optarg) < 0) {
1132 		RTE_LOG(ERR, USER1, "Authentication algorithm specified "
1133 				"not supported!\n");
1134 		return -1;
1135 	}
1136 
1137 	return 0;
1138 }
1139 
1140 static int
1141 parse_auth_op(enum rte_crypto_auth_operation *op, char *optarg)
1142 {
1143 	if (strcmp("VERIFY", optarg) == 0) {
1144 		*op = RTE_CRYPTO_AUTH_OP_VERIFY;
1145 		return 0;
1146 	} else if (strcmp("GENERATE", optarg) == 0) {
1147 		*op = RTE_CRYPTO_AUTH_OP_GENERATE;
1148 		return 0;
1149 	}
1150 
1151 	printf("Authentication operation specified not supported!\n");
1152 	return -1;
1153 }
1154 
1155 static int
1156 parse_aead_algo(enum rte_crypto_aead_algorithm *algo, char *optarg)
1157 {
1158 	if (rte_cryptodev_get_aead_algo_enum(algo, optarg) < 0) {
1159 		RTE_LOG(ERR, USER1, "AEAD algorithm specified "
1160 				"not supported!\n");
1161 		return -1;
1162 	}
1163 
1164 	return 0;
1165 }
1166 
1167 static int
1168 parse_aead_op(enum rte_crypto_aead_operation *op, char *optarg)
1169 {
1170 	if (strcmp("ENCRYPT", optarg) == 0) {
1171 		*op = RTE_CRYPTO_AEAD_OP_ENCRYPT;
1172 		return 0;
1173 	} else if (strcmp("DECRYPT", optarg) == 0) {
1174 		*op = RTE_CRYPTO_AEAD_OP_DECRYPT;
1175 		return 0;
1176 	}
1177 
1178 	printf("AEAD operation specified not supported!\n");
1179 	return -1;
1180 }
1181 static int
1182 parse_cryptodev_mask(struct l2fwd_crypto_options *options,
1183 		const char *q_arg)
1184 {
1185 	char *end = NULL;
1186 	uint64_t pm;
1187 
1188 	/* parse hexadecimal string */
1189 	pm = strtoul(q_arg, &end, 16);
1190 	if ((pm == '\0') || (end == NULL) || (*end != '\0'))
1191 		pm = 0;
1192 
1193 	options->cryptodev_mask = pm;
1194 	if (options->cryptodev_mask == 0) {
1195 		printf("invalid cryptodev_mask specified\n");
1196 		return -1;
1197 	}
1198 
1199 	return 0;
1200 }
1201 
1202 /** Parse long options */
1203 static int
1204 l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,
1205 		struct option *lgopts, int option_index)
1206 {
1207 	int retval;
1208 
1209 	if (strcmp(lgopts[option_index].name, "cdev_type") == 0) {
1210 		retval = parse_cryptodev_type(&options->type, optarg);
1211 		if (retval == 0)
1212 			snprintf(options->string_type, MAX_STR_LEN,
1213 				"%s", optarg);
1214 		return retval;
1215 	}
1216 
1217 	else if (strcmp(lgopts[option_index].name, "chain") == 0)
1218 		return parse_crypto_opt_chain(options, optarg);
1219 
1220 	/* Cipher options */
1221 	else if (strcmp(lgopts[option_index].name, "cipher_algo") == 0)
1222 		return parse_cipher_algo(&options->cipher_xform.cipher.algo,
1223 				optarg);
1224 
1225 	else if (strcmp(lgopts[option_index].name, "cipher_op") == 0)
1226 		return parse_cipher_op(&options->cipher_xform.cipher.op,
1227 				optarg);
1228 
1229 	else if (strcmp(lgopts[option_index].name, "cipher_key") == 0) {
1230 		options->ckey_param = 1;
1231 		options->cipher_xform.cipher.key.length =
1232 			parse_key(options->cipher_xform.cipher.key.data, optarg);
1233 		if (options->cipher_xform.cipher.key.length > 0)
1234 			return 0;
1235 		else
1236 			return -1;
1237 	}
1238 
1239 	else if (strcmp(lgopts[option_index].name, "cipher_key_random_size") == 0)
1240 		return parse_size(&options->ckey_random_size, optarg);
1241 
1242 	else if (strcmp(lgopts[option_index].name, "cipher_iv") == 0) {
1243 		options->cipher_iv_param = 1;
1244 		options->cipher_iv.length =
1245 			parse_key(options->cipher_iv.data, optarg);
1246 		if (options->cipher_iv.length > 0)
1247 			return 0;
1248 		else
1249 			return -1;
1250 	}
1251 
1252 	else if (strcmp(lgopts[option_index].name, "cipher_iv_random_size") == 0)
1253 		return parse_size(&options->cipher_iv_random_size, optarg);
1254 
1255 	/* Authentication options */
1256 	else if (strcmp(lgopts[option_index].name, "auth_algo") == 0) {
1257 		return parse_auth_algo(&options->auth_xform.auth.algo,
1258 				optarg);
1259 	}
1260 
1261 	else if (strcmp(lgopts[option_index].name, "auth_op") == 0)
1262 		return parse_auth_op(&options->auth_xform.auth.op,
1263 				optarg);
1264 
1265 	else if (strcmp(lgopts[option_index].name, "auth_key") == 0) {
1266 		options->akey_param = 1;
1267 		options->auth_xform.auth.key.length =
1268 			parse_key(options->auth_xform.auth.key.data, optarg);
1269 		if (options->auth_xform.auth.key.length > 0)
1270 			return 0;
1271 		else
1272 			return -1;
1273 	}
1274 
1275 	else if (strcmp(lgopts[option_index].name, "auth_key_random_size") == 0) {
1276 		return parse_size(&options->akey_random_size, optarg);
1277 	}
1278 
1279 	else if (strcmp(lgopts[option_index].name, "auth_iv") == 0) {
1280 		options->auth_iv_param = 1;
1281 		options->auth_iv.length =
1282 			parse_key(options->auth_iv.data, optarg);
1283 		if (options->auth_iv.length > 0)
1284 			return 0;
1285 		else
1286 			return -1;
1287 	}
1288 
1289 	else if (strcmp(lgopts[option_index].name, "auth_iv_random_size") == 0)
1290 		return parse_size(&options->auth_iv_random_size, optarg);
1291 
1292 	/* AEAD options */
1293 	else if (strcmp(lgopts[option_index].name, "aead_algo") == 0) {
1294 		return parse_aead_algo(&options->aead_xform.aead.algo,
1295 				optarg);
1296 	}
1297 
1298 	else if (strcmp(lgopts[option_index].name, "aead_op") == 0)
1299 		return parse_aead_op(&options->aead_xform.aead.op,
1300 				optarg);
1301 
1302 	else if (strcmp(lgopts[option_index].name, "aead_key") == 0) {
1303 		options->aead_key_param = 1;
1304 		options->aead_xform.aead.key.length =
1305 			parse_key(options->aead_xform.aead.key.data, optarg);
1306 		if (options->aead_xform.aead.key.length > 0)
1307 			return 0;
1308 		else
1309 			return -1;
1310 	}
1311 
1312 	else if (strcmp(lgopts[option_index].name, "aead_key_random_size") == 0)
1313 		return parse_size(&options->aead_key_random_size, optarg);
1314 
1315 
1316 	else if (strcmp(lgopts[option_index].name, "aead_iv") == 0) {
1317 		options->aead_iv_param = 1;
1318 		options->aead_iv.length =
1319 			parse_key(options->aead_iv.data, optarg);
1320 		if (options->aead_iv.length > 0)
1321 			return 0;
1322 		else
1323 			return -1;
1324 	}
1325 
1326 	else if (strcmp(lgopts[option_index].name, "aead_iv_random_size") == 0)
1327 		return parse_size(&options->aead_iv_random_size, optarg);
1328 
1329 	else if (strcmp(lgopts[option_index].name, "aad") == 0) {
1330 		options->aad_param = 1;
1331 		options->aad.length =
1332 			parse_key(options->aad.data, optarg);
1333 		if (options->aad.length > 0)
1334 			return 0;
1335 		else
1336 			return -1;
1337 	}
1338 
1339 	else if (strcmp(lgopts[option_index].name, "aad_random_size") == 0) {
1340 		return parse_size(&options->aad_random_size, optarg);
1341 	}
1342 
1343 	else if (strcmp(lgopts[option_index].name, "digest_size") == 0) {
1344 		return parse_size(&options->digest_size, optarg);
1345 	}
1346 
1347 	else if (strcmp(lgopts[option_index].name, "sessionless") == 0) {
1348 		options->sessionless = 1;
1349 		return 0;
1350 	}
1351 
1352 	else if (strcmp(lgopts[option_index].name, "cryptodev_mask") == 0)
1353 		return parse_cryptodev_mask(options, optarg);
1354 
1355 	else if (strcmp(lgopts[option_index].name, "mac-updating") == 0) {
1356 		options->mac_updating = 1;
1357 		return 0;
1358 	}
1359 
1360 	else if (strcmp(lgopts[option_index].name, "no-mac-updating") == 0) {
1361 		options->mac_updating = 0;
1362 		return 0;
1363 	}
1364 
1365 	return -1;
1366 }
1367 
1368 /** Parse port mask */
1369 static int
1370 l2fwd_crypto_parse_portmask(struct l2fwd_crypto_options *options,
1371 		const char *q_arg)
1372 {
1373 	char *end = NULL;
1374 	unsigned long pm;
1375 
1376 	/* parse hexadecimal string */
1377 	pm = strtoul(q_arg, &end, 16);
1378 	if ((pm == '\0') || (end == NULL) || (*end != '\0'))
1379 		pm = 0;
1380 
1381 	options->portmask = pm;
1382 	if (options->portmask == 0) {
1383 		printf("invalid portmask specified\n");
1384 		return -1;
1385 	}
1386 
1387 	return pm;
1388 }
1389 
1390 /** Parse number of queues */
1391 static int
1392 l2fwd_crypto_parse_nqueue(struct l2fwd_crypto_options *options,
1393 		const char *q_arg)
1394 {
1395 	char *end = NULL;
1396 	unsigned long n;
1397 
1398 	/* parse hexadecimal string */
1399 	n = strtoul(q_arg, &end, 10);
1400 	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1401 		n = 0;
1402 	else if (n >= MAX_RX_QUEUE_PER_LCORE)
1403 		n = 0;
1404 
1405 	options->nb_ports_per_lcore = n;
1406 	if (options->nb_ports_per_lcore == 0) {
1407 		printf("invalid number of ports selected\n");
1408 		return -1;
1409 	}
1410 
1411 	return 0;
1412 }
1413 
1414 /** Parse timer period */
1415 static int
1416 l2fwd_crypto_parse_timer_period(struct l2fwd_crypto_options *options,
1417 		const char *q_arg)
1418 {
1419 	char *end = NULL;
1420 	unsigned long n;
1421 
1422 	/* parse number string */
1423 	n = (unsigned)strtol(q_arg, &end, 10);
1424 	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1425 		n = 0;
1426 
1427 	if (n >= MAX_TIMER_PERIOD) {
1428 		printf("Warning refresh period specified %lu is greater than "
1429 				"max value %lu! using max value",
1430 				n, MAX_TIMER_PERIOD);
1431 		n = MAX_TIMER_PERIOD;
1432 	}
1433 
1434 	options->refresh_period = n * 1000 * TIMER_MILLISECOND;
1435 
1436 	return 0;
1437 }
1438 
1439 /** Generate default options for application */
1440 static void
1441 l2fwd_crypto_default_options(struct l2fwd_crypto_options *options)
1442 {
1443 	options->portmask = 0xffffffff;
1444 	options->nb_ports_per_lcore = 1;
1445 	options->refresh_period = 10000;
1446 	options->single_lcore = 0;
1447 	options->sessionless = 0;
1448 
1449 	options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;
1450 
1451 	/* Cipher Data */
1452 	options->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1453 	options->cipher_xform.next = NULL;
1454 	options->ckey_param = 0;
1455 	options->ckey_random_size = -1;
1456 	options->cipher_xform.cipher.key.length = 0;
1457 	options->cipher_iv_param = 0;
1458 	options->cipher_iv_random_size = -1;
1459 	options->cipher_iv.length = 0;
1460 
1461 	options->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
1462 	options->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
1463 
1464 	/* Authentication Data */
1465 	options->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
1466 	options->auth_xform.next = NULL;
1467 	options->akey_param = 0;
1468 	options->akey_random_size = -1;
1469 	options->auth_xform.auth.key.length = 0;
1470 	options->auth_iv_param = 0;
1471 	options->auth_iv_random_size = -1;
1472 	options->auth_iv.length = 0;
1473 
1474 	options->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
1475 	options->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
1476 
1477 	/* AEAD Data */
1478 	options->aead_xform.type = RTE_CRYPTO_SYM_XFORM_AEAD;
1479 	options->aead_xform.next = NULL;
1480 	options->aead_key_param = 0;
1481 	options->aead_key_random_size = -1;
1482 	options->aead_xform.aead.key.length = 0;
1483 	options->aead_iv_param = 0;
1484 	options->aead_iv_random_size = -1;
1485 	options->aead_iv.length = 0;
1486 
1487 	options->auth_xform.aead.algo = RTE_CRYPTO_AEAD_AES_GCM;
1488 	options->auth_xform.aead.op = RTE_CRYPTO_AEAD_OP_ENCRYPT;
1489 
1490 	options->aad_param = 0;
1491 	options->aad_random_size = -1;
1492 	options->aad.length = 0;
1493 
1494 	options->digest_size = -1;
1495 
1496 	options->type = CDEV_TYPE_ANY;
1497 	options->cryptodev_mask = UINT64_MAX;
1498 
1499 	options->mac_updating = 1;
1500 }
1501 
1502 static void
1503 display_cipher_info(struct l2fwd_crypto_options *options)
1504 {
1505 	printf("\n---- Cipher information ---\n");
1506 	printf("Algorithm: %s\n",
1507 		rte_crypto_cipher_algorithm_strings[options->cipher_xform.cipher.algo]);
1508 	rte_hexdump(stdout, "Cipher key:",
1509 			options->cipher_xform.cipher.key.data,
1510 			options->cipher_xform.cipher.key.length);
1511 	rte_hexdump(stdout, "IV:", options->cipher_iv.data, options->cipher_iv.length);
1512 }
1513 
1514 static void
1515 display_auth_info(struct l2fwd_crypto_options *options)
1516 {
1517 	printf("\n---- Authentication information ---\n");
1518 	printf("Algorithm: %s\n",
1519 		rte_crypto_auth_algorithm_strings[options->auth_xform.auth.algo]);
1520 	rte_hexdump(stdout, "Auth key:",
1521 			options->auth_xform.auth.key.data,
1522 			options->auth_xform.auth.key.length);
1523 	rte_hexdump(stdout, "IV:", options->auth_iv.data, options->auth_iv.length);
1524 }
1525 
1526 static void
1527 display_aead_info(struct l2fwd_crypto_options *options)
1528 {
1529 	printf("\n---- AEAD information ---\n");
1530 	printf("Algorithm: %s\n",
1531 		rte_crypto_aead_algorithm_strings[options->aead_xform.aead.algo]);
1532 	rte_hexdump(stdout, "AEAD key:",
1533 			options->aead_xform.aead.key.data,
1534 			options->aead_xform.aead.key.length);
1535 	rte_hexdump(stdout, "IV:", options->aead_iv.data, options->aead_iv.length);
1536 	rte_hexdump(stdout, "AAD:", options->aad.data, options->aad.length);
1537 }
1538 
1539 static void
1540 l2fwd_crypto_options_print(struct l2fwd_crypto_options *options)
1541 {
1542 	char string_cipher_op[MAX_STR_LEN];
1543 	char string_auth_op[MAX_STR_LEN];
1544 	char string_aead_op[MAX_STR_LEN];
1545 
1546 	if (options->cipher_xform.cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
1547 		strcpy(string_cipher_op, "Encrypt");
1548 	else
1549 		strcpy(string_cipher_op, "Decrypt");
1550 
1551 	if (options->auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_GENERATE)
1552 		strcpy(string_auth_op, "Auth generate");
1553 	else
1554 		strcpy(string_auth_op, "Auth verify");
1555 
1556 	if (options->aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_ENCRYPT)
1557 		strcpy(string_aead_op, "Authenticated encryption");
1558 	else
1559 		strcpy(string_aead_op, "Authenticated decryption");
1560 
1561 
1562 	printf("Options:-\nn");
1563 	printf("portmask: %x\n", options->portmask);
1564 	printf("ports per lcore: %u\n", options->nb_ports_per_lcore);
1565 	printf("refresh period : %u\n", options->refresh_period);
1566 	printf("single lcore mode: %s\n",
1567 			options->single_lcore ? "enabled" : "disabled");
1568 	printf("stats_printing: %s\n",
1569 			options->refresh_period == 0 ? "disabled" : "enabled");
1570 
1571 	printf("sessionless crypto: %s\n",
1572 			options->sessionless ? "enabled" : "disabled");
1573 
1574 	if (options->ckey_param && (options->ckey_random_size != -1))
1575 		printf("Cipher key already parsed, ignoring size of random key\n");
1576 
1577 	if (options->akey_param && (options->akey_random_size != -1))
1578 		printf("Auth key already parsed, ignoring size of random key\n");
1579 
1580 	if (options->cipher_iv_param && (options->cipher_iv_random_size != -1))
1581 		printf("Cipher IV already parsed, ignoring size of random IV\n");
1582 
1583 	if (options->auth_iv_param && (options->auth_iv_random_size != -1))
1584 		printf("Auth IV already parsed, ignoring size of random IV\n");
1585 
1586 	if (options->aad_param && (options->aad_random_size != -1))
1587 		printf("AAD already parsed, ignoring size of random AAD\n");
1588 
1589 	printf("\nCrypto chain: ");
1590 	switch (options->xform_chain) {
1591 	case L2FWD_CRYPTO_AEAD:
1592 		printf("Input --> %s --> Output\n", string_aead_op);
1593 		display_aead_info(options);
1594 		break;
1595 	case L2FWD_CRYPTO_CIPHER_HASH:
1596 		printf("Input --> %s --> %s --> Output\n",
1597 			string_cipher_op, string_auth_op);
1598 		display_cipher_info(options);
1599 		display_auth_info(options);
1600 		break;
1601 	case L2FWD_CRYPTO_HASH_CIPHER:
1602 		printf("Input --> %s --> %s --> Output\n",
1603 			string_auth_op, string_cipher_op);
1604 		display_cipher_info(options);
1605 		display_auth_info(options);
1606 		break;
1607 	case L2FWD_CRYPTO_HASH_ONLY:
1608 		printf("Input --> %s --> Output\n", string_auth_op);
1609 		display_auth_info(options);
1610 		break;
1611 	case L2FWD_CRYPTO_CIPHER_ONLY:
1612 		printf("Input --> %s --> Output\n", string_cipher_op);
1613 		display_cipher_info(options);
1614 		break;
1615 	}
1616 }
1617 
1618 /* Parse the argument given in the command line of the application */
1619 static int
1620 l2fwd_crypto_parse_args(struct l2fwd_crypto_options *options,
1621 		int argc, char **argv)
1622 {
1623 	int opt, retval, option_index;
1624 	char **argvopt = argv, *prgname = argv[0];
1625 
1626 	static struct option lgopts[] = {
1627 			{ "sessionless", no_argument, 0, 0 },
1628 
1629 			{ "cdev_type", required_argument, 0, 0 },
1630 			{ "chain", required_argument, 0, 0 },
1631 
1632 			{ "cipher_algo", required_argument, 0, 0 },
1633 			{ "cipher_op", required_argument, 0, 0 },
1634 			{ "cipher_key", required_argument, 0, 0 },
1635 			{ "cipher_key_random_size", required_argument, 0, 0 },
1636 			{ "cipher_iv", required_argument, 0, 0 },
1637 			{ "cipher_iv_random_size", required_argument, 0, 0 },
1638 
1639 			{ "auth_algo", required_argument, 0, 0 },
1640 			{ "auth_op", required_argument, 0, 0 },
1641 			{ "auth_key", required_argument, 0, 0 },
1642 			{ "auth_key_random_size", required_argument, 0, 0 },
1643 			{ "auth_iv", required_argument, 0, 0 },
1644 			{ "auth_iv_random_size", required_argument, 0, 0 },
1645 
1646 			{ "aead_algo", required_argument, 0, 0 },
1647 			{ "aead_op", required_argument, 0, 0 },
1648 			{ "aead_key", required_argument, 0, 0 },
1649 			{ "aead_key_random_size", required_argument, 0, 0 },
1650 			{ "aead_iv", required_argument, 0, 0 },
1651 			{ "aead_iv_random_size", required_argument, 0, 0 },
1652 
1653 			{ "aad", required_argument, 0, 0 },
1654 			{ "aad_random_size", required_argument, 0, 0 },
1655 
1656 			{ "digest_size", required_argument, 0, 0 },
1657 
1658 			{ "sessionless", no_argument, 0, 0 },
1659 			{ "cryptodev_mask", required_argument, 0, 0},
1660 
1661 			{ "mac-updating", no_argument, 0, 0},
1662 			{ "no-mac-updating", no_argument, 0, 0},
1663 
1664 			{ NULL, 0, 0, 0 }
1665 	};
1666 
1667 	l2fwd_crypto_default_options(options);
1668 
1669 	while ((opt = getopt_long(argc, argvopt, "p:q:sT:", lgopts,
1670 			&option_index)) != EOF) {
1671 		switch (opt) {
1672 		/* long options */
1673 		case 0:
1674 			retval = l2fwd_crypto_parse_args_long_options(options,
1675 					lgopts, option_index);
1676 			if (retval < 0) {
1677 				l2fwd_crypto_usage(prgname);
1678 				return -1;
1679 			}
1680 			break;
1681 
1682 		/* portmask */
1683 		case 'p':
1684 			retval = l2fwd_crypto_parse_portmask(options, optarg);
1685 			if (retval < 0) {
1686 				l2fwd_crypto_usage(prgname);
1687 				return -1;
1688 			}
1689 			break;
1690 
1691 		/* nqueue */
1692 		case 'q':
1693 			retval = l2fwd_crypto_parse_nqueue(options, optarg);
1694 			if (retval < 0) {
1695 				l2fwd_crypto_usage(prgname);
1696 				return -1;
1697 			}
1698 			break;
1699 
1700 		/* single  */
1701 		case 's':
1702 			options->single_lcore = 1;
1703 
1704 			break;
1705 
1706 		/* timer period */
1707 		case 'T':
1708 			retval = l2fwd_crypto_parse_timer_period(options,
1709 					optarg);
1710 			if (retval < 0) {
1711 				l2fwd_crypto_usage(prgname);
1712 				return -1;
1713 			}
1714 			break;
1715 
1716 		default:
1717 			l2fwd_crypto_usage(prgname);
1718 			return -1;
1719 		}
1720 	}
1721 
1722 
1723 	if (optind >= 0)
1724 		argv[optind-1] = prgname;
1725 
1726 	retval = optind-1;
1727 	optind = 1; /* reset getopt lib */
1728 
1729 	return retval;
1730 }
1731 
1732 /* Check the link status of all ports in up to 9s, and print them finally */
1733 static void
1734 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
1735 {
1736 #define CHECK_INTERVAL 100 /* 100ms */
1737 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
1738 	uint8_t portid, count, all_ports_up, print_flag = 0;
1739 	struct rte_eth_link link;
1740 
1741 	printf("\nChecking link status");
1742 	fflush(stdout);
1743 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
1744 		all_ports_up = 1;
1745 		for (portid = 0; portid < port_num; portid++) {
1746 			if ((port_mask & (1 << portid)) == 0)
1747 				continue;
1748 			memset(&link, 0, sizeof(link));
1749 			rte_eth_link_get_nowait(portid, &link);
1750 			/* print link status if flag set */
1751 			if (print_flag == 1) {
1752 				if (link.link_status)
1753 					printf("Port %d Link Up - speed %u "
1754 						"Mbps - %s\n", (uint8_t)portid,
1755 						(unsigned)link.link_speed,
1756 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
1757 					("full-duplex") : ("half-duplex\n"));
1758 				else
1759 					printf("Port %d Link Down\n",
1760 						(uint8_t)portid);
1761 				continue;
1762 			}
1763 			/* clear all_ports_up flag if any link down */
1764 			if (link.link_status == ETH_LINK_DOWN) {
1765 				all_ports_up = 0;
1766 				break;
1767 			}
1768 		}
1769 		/* after finally printing all link status, get out */
1770 		if (print_flag == 1)
1771 			break;
1772 
1773 		if (all_ports_up == 0) {
1774 			printf(".");
1775 			fflush(stdout);
1776 			rte_delay_ms(CHECK_INTERVAL);
1777 		}
1778 
1779 		/* set the print_flag if all ports up or timeout */
1780 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
1781 			print_flag = 1;
1782 			printf("done\n");
1783 		}
1784 	}
1785 }
1786 
1787 /* Check if device has to be HW/SW or any */
1788 static int
1789 check_type(const struct l2fwd_crypto_options *options,
1790 		const struct rte_cryptodev_info *dev_info)
1791 {
1792 	if (options->type == CDEV_TYPE_HW &&
1793 			(dev_info->feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED))
1794 		return 0;
1795 	if (options->type == CDEV_TYPE_SW &&
1796 			!(dev_info->feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED))
1797 		return 0;
1798 	if (options->type == CDEV_TYPE_ANY)
1799 		return 0;
1800 
1801 	return -1;
1802 }
1803 
1804 static const struct rte_cryptodev_capabilities *
1805 check_device_support_cipher_algo(const struct l2fwd_crypto_options *options,
1806 		const struct rte_cryptodev_info *dev_info,
1807 		uint8_t cdev_id)
1808 {
1809 	unsigned int i = 0;
1810 	const struct rte_cryptodev_capabilities *cap = &dev_info->capabilities[0];
1811 	enum rte_crypto_cipher_algorithm cap_cipher_algo;
1812 	enum rte_crypto_cipher_algorithm opt_cipher_algo =
1813 					options->cipher_xform.cipher.algo;
1814 
1815 	while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1816 		cap_cipher_algo = cap->sym.cipher.algo;
1817 		if (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
1818 			if (cap_cipher_algo == opt_cipher_algo) {
1819 				if (check_type(options, dev_info) == 0)
1820 					break;
1821 			}
1822 		}
1823 		cap = &dev_info->capabilities[++i];
1824 	}
1825 
1826 	if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1827 		printf("Algorithm %s not supported by cryptodev %u"
1828 			" or device not of preferred type (%s)\n",
1829 			rte_crypto_cipher_algorithm_strings[opt_cipher_algo],
1830 			cdev_id,
1831 			options->string_type);
1832 		return NULL;
1833 	}
1834 
1835 	return cap;
1836 }
1837 
1838 static const struct rte_cryptodev_capabilities *
1839 check_device_support_auth_algo(const struct l2fwd_crypto_options *options,
1840 		const struct rte_cryptodev_info *dev_info,
1841 		uint8_t cdev_id)
1842 {
1843 	unsigned int i = 0;
1844 	const struct rte_cryptodev_capabilities *cap = &dev_info->capabilities[0];
1845 	enum rte_crypto_auth_algorithm cap_auth_algo;
1846 	enum rte_crypto_auth_algorithm opt_auth_algo =
1847 					options->auth_xform.auth.algo;
1848 
1849 	while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1850 		cap_auth_algo = cap->sym.auth.algo;
1851 		if (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AUTH) {
1852 			if (cap_auth_algo == opt_auth_algo) {
1853 				if (check_type(options, dev_info) == 0)
1854 					break;
1855 			}
1856 		}
1857 		cap = &dev_info->capabilities[++i];
1858 	}
1859 
1860 	if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1861 		printf("Algorithm %s not supported by cryptodev %u"
1862 			" or device not of preferred type (%s)\n",
1863 			rte_crypto_auth_algorithm_strings[opt_auth_algo],
1864 			cdev_id,
1865 			options->string_type);
1866 		return NULL;
1867 	}
1868 
1869 	return cap;
1870 }
1871 
1872 static const struct rte_cryptodev_capabilities *
1873 check_device_support_aead_algo(const struct l2fwd_crypto_options *options,
1874 		const struct rte_cryptodev_info *dev_info,
1875 		uint8_t cdev_id)
1876 {
1877 	unsigned int i = 0;
1878 	const struct rte_cryptodev_capabilities *cap = &dev_info->capabilities[0];
1879 	enum rte_crypto_aead_algorithm cap_aead_algo;
1880 	enum rte_crypto_aead_algorithm opt_aead_algo =
1881 					options->aead_xform.aead.algo;
1882 
1883 	while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1884 		cap_aead_algo = cap->sym.aead.algo;
1885 		if (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AEAD) {
1886 			if (cap_aead_algo == opt_aead_algo) {
1887 				if (check_type(options, dev_info) == 0)
1888 					break;
1889 			}
1890 		}
1891 		cap = &dev_info->capabilities[++i];
1892 	}
1893 
1894 	if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1895 		printf("Algorithm %s not supported by cryptodev %u"
1896 			" or device not of preferred type (%s)\n",
1897 			rte_crypto_aead_algorithm_strings[opt_aead_algo],
1898 			cdev_id,
1899 			options->string_type);
1900 		return NULL;
1901 	}
1902 
1903 	return cap;
1904 }
1905 
1906 /* Check if the device is enabled by cryptodev_mask */
1907 static int
1908 check_cryptodev_mask(struct l2fwd_crypto_options *options,
1909 		uint8_t cdev_id)
1910 {
1911 	if (options->cryptodev_mask & (1 << cdev_id))
1912 		return 0;
1913 
1914 	return -1;
1915 }
1916 
1917 static inline int
1918 check_supported_size(uint16_t length, uint16_t min, uint16_t max,
1919 		uint16_t increment)
1920 {
1921 	uint16_t supp_size;
1922 
1923 	/* Single value */
1924 	if (increment == 0) {
1925 		if (length == min)
1926 			return 0;
1927 		else
1928 			return -1;
1929 	}
1930 
1931 	/* Range of values */
1932 	for (supp_size = min; supp_size <= max; supp_size += increment) {
1933 		if (length == supp_size)
1934 			return 0;
1935 	}
1936 
1937 	return -1;
1938 }
1939 
1940 static int
1941 check_iv_param(const struct rte_crypto_param_range *iv_range_size,
1942 		unsigned int iv_param, int iv_random_size,
1943 		uint16_t *iv_length)
1944 {
1945 	/*
1946 	 * Check if length of provided IV is supported
1947 	 * by the algorithm chosen.
1948 	 */
1949 	if (iv_param) {
1950 		if (check_supported_size(*iv_length,
1951 				iv_range_size->min,
1952 				iv_range_size->max,
1953 				iv_range_size->increment)
1954 					!= 0) {
1955 			printf("Unsupported IV length\n");
1956 			return -1;
1957 		}
1958 	/*
1959 	 * Check if length of IV to be randomly generated
1960 	 * is supported by the algorithm chosen.
1961 	 */
1962 	} else if (iv_random_size != -1) {
1963 		if (check_supported_size(iv_random_size,
1964 				iv_range_size->min,
1965 				iv_range_size->max,
1966 				iv_range_size->increment)
1967 					!= 0) {
1968 			printf("Unsupported IV length\n");
1969 			return -1;
1970 		}
1971 		*iv_length = iv_random_size;
1972 	/* No size provided, use minimum size. */
1973 	} else
1974 		*iv_length = iv_range_size->min;
1975 
1976 	return 0;
1977 }
1978 
1979 static int
1980 initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports,
1981 		uint8_t *enabled_cdevs)
1982 {
1983 	unsigned int cdev_id, cdev_count, enabled_cdev_count = 0;
1984 	const struct rte_cryptodev_capabilities *cap;
1985 	unsigned int sess_sz, max_sess_sz = 0;
1986 	int retval;
1987 
1988 	cdev_count = rte_cryptodev_count();
1989 	if (cdev_count == 0) {
1990 		printf("No crypto devices available\n");
1991 		return -1;
1992 	}
1993 
1994 	for (cdev_id = 0; cdev_id < cdev_count; cdev_id++) {
1995 		sess_sz = rte_cryptodev_get_private_session_size(cdev_id);
1996 		if (sess_sz > max_sess_sz)
1997 			max_sess_sz = sess_sz;
1998 	}
1999 
2000 	for (cdev_id = 0; cdev_id < cdev_count && enabled_cdev_count < nb_ports;
2001 			cdev_id++) {
2002 		struct rte_cryptodev_qp_conf qp_conf;
2003 		struct rte_cryptodev_info dev_info;
2004 		retval = rte_cryptodev_socket_id(cdev_id);
2005 
2006 		if (retval < 0) {
2007 			printf("Invalid crypto device id used\n");
2008 			return -1;
2009 		}
2010 
2011 		uint8_t socket_id = (uint8_t) retval;
2012 
2013 		struct rte_cryptodev_config conf = {
2014 			.nb_queue_pairs = 1,
2015 			.socket_id = socket_id,
2016 		};
2017 
2018 		if (check_cryptodev_mask(options, (uint8_t)cdev_id))
2019 			continue;
2020 
2021 		rte_cryptodev_info_get(cdev_id, &dev_info);
2022 
2023 		if (session_pool_socket[socket_id] == NULL) {
2024 			char mp_name[RTE_MEMPOOL_NAMESIZE];
2025 			struct rte_mempool *sess_mp;
2026 
2027 			snprintf(mp_name, RTE_MEMPOOL_NAMESIZE,
2028 				"sess_mp_%u", socket_id);
2029 
2030 			/*
2031 			 * Create enough objects for session headers and
2032 			 * device private data
2033 			 */
2034 			sess_mp = rte_mempool_create(mp_name,
2035 						MAX_SESSIONS * 2,
2036 						max_sess_sz,
2037 						SESSION_POOL_CACHE_SIZE,
2038 						0, NULL, NULL, NULL,
2039 						NULL, socket_id,
2040 						0);
2041 
2042 			if (sess_mp == NULL) {
2043 				printf("Cannot create session pool on socket %d\n",
2044 					socket_id);
2045 				return -ENOMEM;
2046 			}
2047 
2048 			printf("Allocated session pool on socket %d\n", socket_id);
2049 			session_pool_socket[socket_id] = sess_mp;
2050 		}
2051 
2052 		/* Set AEAD parameters */
2053 		if (options->xform_chain == L2FWD_CRYPTO_AEAD) {
2054 			/* Check if device supports AEAD algo */
2055 			cap = check_device_support_aead_algo(options, &dev_info,
2056 							cdev_id);
2057 			if (cap == NULL)
2058 				continue;
2059 
2060 			options->block_size = cap->sym.aead.block_size;
2061 
2062 			check_iv_param(&cap->sym.aead.iv_size,
2063 					options->aead_iv_param,
2064 					options->aead_iv_random_size,
2065 					&options->aead_iv.length);
2066 
2067 			/*
2068 			 * Check if length of provided AEAD key is supported
2069 			 * by the algorithm chosen.
2070 			 */
2071 			if (options->aead_key_param) {
2072 				if (check_supported_size(
2073 						options->aead_xform.aead.key.length,
2074 						cap->sym.aead.key_size.min,
2075 						cap->sym.aead.key_size.max,
2076 						cap->sym.aead.key_size.increment)
2077 							!= 0) {
2078 					printf("Unsupported aead key length\n");
2079 					return -1;
2080 				}
2081 			/*
2082 			 * Check if length of the aead key to be randomly generated
2083 			 * is supported by the algorithm chosen.
2084 			 */
2085 			} else if (options->aead_key_random_size != -1) {
2086 				if (check_supported_size(options->aead_key_random_size,
2087 						cap->sym.aead.key_size.min,
2088 						cap->sym.aead.key_size.max,
2089 						cap->sym.aead.key_size.increment)
2090 							!= 0) {
2091 					printf("Unsupported aead key length\n");
2092 					return -1;
2093 				}
2094 				options->aead_xform.aead.key.length =
2095 							options->aead_key_random_size;
2096 			/* No size provided, use minimum size. */
2097 			} else
2098 				options->aead_xform.aead.key.length =
2099 						cap->sym.aead.key_size.min;
2100 
2101 			if (!options->aead_key_param)
2102 				generate_random_key(
2103 					options->aead_xform.aead.key.data,
2104 					options->aead_xform.aead.key.length);
2105 
2106 			/*
2107 			 * Check if length of provided AAD is supported
2108 			 * by the algorithm chosen.
2109 			 */
2110 			if (options->aad_param) {
2111 				if (check_supported_size(options->aad.length,
2112 						cap->sym.aead.aad_size.min,
2113 						cap->sym.aead.aad_size.max,
2114 						cap->sym.aead.aad_size.increment)
2115 							!= 0) {
2116 					printf("Unsupported AAD length\n");
2117 					return -1;
2118 				}
2119 			/*
2120 			 * Check if length of AAD to be randomly generated
2121 			 * is supported by the algorithm chosen.
2122 			 */
2123 			} else if (options->aad_random_size != -1) {
2124 				if (check_supported_size(options->aad_random_size,
2125 						cap->sym.aead.aad_size.min,
2126 						cap->sym.aead.aad_size.max,
2127 						cap->sym.aead.aad_size.increment)
2128 							!= 0) {
2129 					printf("Unsupported AAD length\n");
2130 					return -1;
2131 				}
2132 				options->aad.length = options->aad_random_size;
2133 			/* No size provided, use minimum size. */
2134 			} else
2135 				options->aad.length = cap->sym.auth.aad_size.min;
2136 
2137 			options->aead_xform.aead.aad_length =
2138 						options->aad.length;
2139 
2140 			/* Check if digest size is supported by the algorithm. */
2141 			if (options->digest_size != -1) {
2142 				if (check_supported_size(options->digest_size,
2143 						cap->sym.aead.digest_size.min,
2144 						cap->sym.aead.digest_size.max,
2145 						cap->sym.aead.digest_size.increment)
2146 							!= 0) {
2147 					printf("Unsupported digest length\n");
2148 					return -1;
2149 				}
2150 				options->aead_xform.aead.digest_length =
2151 							options->digest_size;
2152 			/* No size provided, use minimum size. */
2153 			} else
2154 				options->aead_xform.aead.digest_length =
2155 						cap->sym.aead.digest_size.min;
2156 		}
2157 
2158 		/* Set cipher parameters */
2159 		if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
2160 				options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
2161 				options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
2162 			/* Check if device supports cipher algo */
2163 			cap = check_device_support_cipher_algo(options, &dev_info,
2164 							cdev_id);
2165 			if (cap == NULL)
2166 				continue;
2167 
2168 			options->block_size = cap->sym.cipher.block_size;
2169 
2170 			check_iv_param(&cap->sym.cipher.iv_size,
2171 					options->cipher_iv_param,
2172 					options->cipher_iv_random_size,
2173 					&options->cipher_iv.length);
2174 
2175 			/*
2176 			 * Check if length of provided cipher key is supported
2177 			 * by the algorithm chosen.
2178 			 */
2179 			if (options->ckey_param) {
2180 				if (check_supported_size(
2181 						options->cipher_xform.cipher.key.length,
2182 						cap->sym.cipher.key_size.min,
2183 						cap->sym.cipher.key_size.max,
2184 						cap->sym.cipher.key_size.increment)
2185 							!= 0) {
2186 					printf("Unsupported cipher key length\n");
2187 					return -1;
2188 				}
2189 			/*
2190 			 * Check if length of the cipher key to be randomly generated
2191 			 * is supported by the algorithm chosen.
2192 			 */
2193 			} else if (options->ckey_random_size != -1) {
2194 				if (check_supported_size(options->ckey_random_size,
2195 						cap->sym.cipher.key_size.min,
2196 						cap->sym.cipher.key_size.max,
2197 						cap->sym.cipher.key_size.increment)
2198 							!= 0) {
2199 					printf("Unsupported cipher key length\n");
2200 					return -1;
2201 				}
2202 				options->cipher_xform.cipher.key.length =
2203 							options->ckey_random_size;
2204 			/* No size provided, use minimum size. */
2205 			} else
2206 				options->cipher_xform.cipher.key.length =
2207 						cap->sym.cipher.key_size.min;
2208 
2209 			if (!options->ckey_param)
2210 				generate_random_key(
2211 					options->cipher_xform.cipher.key.data,
2212 					options->cipher_xform.cipher.key.length);
2213 
2214 		}
2215 
2216 		/* Set auth parameters */
2217 		if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
2218 				options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
2219 				options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) {
2220 			/* Check if device supports auth algo */
2221 			cap = check_device_support_auth_algo(options, &dev_info,
2222 							cdev_id);
2223 			if (cap == NULL)
2224 				continue;
2225 
2226 			check_iv_param(&cap->sym.auth.iv_size,
2227 					options->auth_iv_param,
2228 					options->auth_iv_random_size,
2229 					&options->auth_iv.length);
2230 			/*
2231 			 * Check if length of provided auth key is supported
2232 			 * by the algorithm chosen.
2233 			 */
2234 			if (options->akey_param) {
2235 				if (check_supported_size(
2236 						options->auth_xform.auth.key.length,
2237 						cap->sym.auth.key_size.min,
2238 						cap->sym.auth.key_size.max,
2239 						cap->sym.auth.key_size.increment)
2240 							!= 0) {
2241 					printf("Unsupported auth key length\n");
2242 					return -1;
2243 				}
2244 			/*
2245 			 * Check if length of the auth key to be randomly generated
2246 			 * is supported by the algorithm chosen.
2247 			 */
2248 			} else if (options->akey_random_size != -1) {
2249 				if (check_supported_size(options->akey_random_size,
2250 						cap->sym.auth.key_size.min,
2251 						cap->sym.auth.key_size.max,
2252 						cap->sym.auth.key_size.increment)
2253 							!= 0) {
2254 					printf("Unsupported auth key length\n");
2255 					return -1;
2256 				}
2257 				options->auth_xform.auth.key.length =
2258 							options->akey_random_size;
2259 			/* No size provided, use minimum size. */
2260 			} else
2261 				options->auth_xform.auth.key.length =
2262 						cap->sym.auth.key_size.min;
2263 
2264 			if (!options->akey_param)
2265 				generate_random_key(
2266 					options->auth_xform.auth.key.data,
2267 					options->auth_xform.auth.key.length);
2268 
2269 			/* Check if digest size is supported by the algorithm. */
2270 			if (options->digest_size != -1) {
2271 				if (check_supported_size(options->digest_size,
2272 						cap->sym.auth.digest_size.min,
2273 						cap->sym.auth.digest_size.max,
2274 						cap->sym.auth.digest_size.increment)
2275 							!= 0) {
2276 					printf("Unsupported digest length\n");
2277 					return -1;
2278 				}
2279 				options->auth_xform.auth.digest_length =
2280 							options->digest_size;
2281 			/* No size provided, use minimum size. */
2282 			} else
2283 				options->auth_xform.auth.digest_length =
2284 						cap->sym.auth.digest_size.min;
2285 		}
2286 
2287 		retval = rte_cryptodev_configure(cdev_id, &conf);
2288 		if (retval < 0) {
2289 			printf("Failed to configure cryptodev %u", cdev_id);
2290 			return -1;
2291 		}
2292 
2293 		qp_conf.nb_descriptors = 2048;
2294 
2295 		retval = rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
2296 				socket_id, session_pool_socket[socket_id]);
2297 		if (retval < 0) {
2298 			printf("Failed to setup queue pair %u on cryptodev %u",
2299 					0, cdev_id);
2300 			return -1;
2301 		}
2302 
2303 		retval = rte_cryptodev_start(cdev_id);
2304 		if (retval < 0) {
2305 			printf("Failed to start device %u: error %d\n",
2306 					cdev_id, retval);
2307 			return -1;
2308 		}
2309 
2310 		l2fwd_enabled_crypto_mask |= (((uint64_t)1) << cdev_id);
2311 
2312 		enabled_cdevs[cdev_id] = 1;
2313 		enabled_cdev_count++;
2314 	}
2315 
2316 	return enabled_cdev_count;
2317 }
2318 
2319 static int
2320 initialize_ports(struct l2fwd_crypto_options *options)
2321 {
2322 	uint8_t last_portid, portid;
2323 	unsigned enabled_portcount = 0;
2324 	unsigned nb_ports = rte_eth_dev_count();
2325 
2326 	if (nb_ports == 0) {
2327 		printf("No Ethernet ports - bye\n");
2328 		return -1;
2329 	}
2330 
2331 	/* Reset l2fwd_dst_ports */
2332 	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
2333 		l2fwd_dst_ports[portid] = 0;
2334 
2335 	for (last_portid = 0, portid = 0; portid < nb_ports; portid++) {
2336 		int retval;
2337 
2338 		/* Skip ports that are not enabled */
2339 		if ((options->portmask & (1 << portid)) == 0)
2340 			continue;
2341 
2342 		/* init port */
2343 		printf("Initializing port %u... ", (unsigned) portid);
2344 		fflush(stdout);
2345 		retval = rte_eth_dev_configure(portid, 1, 1, &port_conf);
2346 		if (retval < 0) {
2347 			printf("Cannot configure device: err=%d, port=%u\n",
2348 				  retval, (unsigned) portid);
2349 			return -1;
2350 		}
2351 
2352 		retval = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
2353 							  &nb_txd);
2354 		if (retval < 0) {
2355 			printf("Cannot adjust number of descriptors: err=%d, port=%u\n",
2356 				retval, (unsigned) portid);
2357 			return -1;
2358 		}
2359 
2360 		/* init one RX queue */
2361 		fflush(stdout);
2362 		retval = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
2363 					     rte_eth_dev_socket_id(portid),
2364 					     NULL, l2fwd_pktmbuf_pool);
2365 		if (retval < 0) {
2366 			printf("rte_eth_rx_queue_setup:err=%d, port=%u\n",
2367 					retval, (unsigned) portid);
2368 			return -1;
2369 		}
2370 
2371 		/* init one TX queue on each port */
2372 		fflush(stdout);
2373 		retval = rte_eth_tx_queue_setup(portid, 0, nb_txd,
2374 				rte_eth_dev_socket_id(portid),
2375 				NULL);
2376 		if (retval < 0) {
2377 			printf("rte_eth_tx_queue_setup:err=%d, port=%u\n",
2378 				retval, (unsigned) portid);
2379 
2380 			return -1;
2381 		}
2382 
2383 		/* Start device */
2384 		retval = rte_eth_dev_start(portid);
2385 		if (retval < 0) {
2386 			printf("rte_eth_dev_start:err=%d, port=%u\n",
2387 					retval, (unsigned) portid);
2388 			return -1;
2389 		}
2390 
2391 		rte_eth_promiscuous_enable(portid);
2392 
2393 		rte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]);
2394 
2395 		printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
2396 				(unsigned) portid,
2397 				l2fwd_ports_eth_addr[portid].addr_bytes[0],
2398 				l2fwd_ports_eth_addr[portid].addr_bytes[1],
2399 				l2fwd_ports_eth_addr[portid].addr_bytes[2],
2400 				l2fwd_ports_eth_addr[portid].addr_bytes[3],
2401 				l2fwd_ports_eth_addr[portid].addr_bytes[4],
2402 				l2fwd_ports_eth_addr[portid].addr_bytes[5]);
2403 
2404 		/* initialize port stats */
2405 		memset(&port_statistics, 0, sizeof(port_statistics));
2406 
2407 		/* Setup port forwarding table */
2408 		if (enabled_portcount % 2) {
2409 			l2fwd_dst_ports[portid] = last_portid;
2410 			l2fwd_dst_ports[last_portid] = portid;
2411 		} else {
2412 			last_portid = portid;
2413 		}
2414 
2415 		l2fwd_enabled_port_mask |= (1 << portid);
2416 		enabled_portcount++;
2417 	}
2418 
2419 	if (enabled_portcount == 1) {
2420 		l2fwd_dst_ports[last_portid] = last_portid;
2421 	} else if (enabled_portcount % 2) {
2422 		printf("odd number of ports in portmask- bye\n");
2423 		return -1;
2424 	}
2425 
2426 	check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);
2427 
2428 	return enabled_portcount;
2429 }
2430 
2431 static void
2432 reserve_key_memory(struct l2fwd_crypto_options *options)
2433 {
2434 	options->cipher_xform.cipher.key.data = rte_malloc("crypto key",
2435 						MAX_KEY_SIZE, 0);
2436 	if (options->cipher_xform.cipher.key.data == NULL)
2437 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for cipher key");
2438 
2439 	options->auth_xform.auth.key.data = rte_malloc("auth key",
2440 						MAX_KEY_SIZE, 0);
2441 	if (options->auth_xform.auth.key.data == NULL)
2442 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for auth key");
2443 
2444 	options->aead_xform.aead.key.data = rte_malloc("aead key",
2445 						MAX_KEY_SIZE, 0);
2446 	if (options->aead_xform.aead.key.data == NULL)
2447 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for AEAD key");
2448 
2449 	options->cipher_iv.data = rte_malloc("cipher iv", MAX_KEY_SIZE, 0);
2450 	if (options->cipher_iv.data == NULL)
2451 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for cipher IV");
2452 
2453 	options->auth_iv.data = rte_malloc("auth iv", MAX_KEY_SIZE, 0);
2454 	if (options->auth_iv.data == NULL)
2455 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for auth IV");
2456 
2457 	options->aead_iv.data = rte_malloc("aead_iv", MAX_KEY_SIZE, 0);
2458 	if (options->aead_iv.data == NULL)
2459 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for AEAD iv");
2460 
2461 	options->aad.data = rte_malloc("aad", MAX_KEY_SIZE, 0);
2462 	if (options->aad.data == NULL)
2463 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for AAD");
2464 	options->aad.phys_addr = rte_malloc_virt2phy(options->aad.data);
2465 }
2466 
2467 int
2468 main(int argc, char **argv)
2469 {
2470 	struct lcore_queue_conf *qconf;
2471 	struct l2fwd_crypto_options options;
2472 
2473 	uint8_t nb_ports, nb_cryptodevs, portid, cdev_id;
2474 	unsigned lcore_id, rx_lcore_id;
2475 	int ret, enabled_cdevcount, enabled_portcount;
2476 	uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = {0};
2477 
2478 	/* init EAL */
2479 	ret = rte_eal_init(argc, argv);
2480 	if (ret < 0)
2481 		rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
2482 	argc -= ret;
2483 	argv += ret;
2484 
2485 	/* reserve memory for Cipher/Auth key and IV */
2486 	reserve_key_memory(&options);
2487 
2488 	/* parse application arguments (after the EAL ones) */
2489 	ret = l2fwd_crypto_parse_args(&options, argc, argv);
2490 	if (ret < 0)
2491 		rte_exit(EXIT_FAILURE, "Invalid L2FWD-CRYPTO arguments\n");
2492 
2493 	printf("MAC updating %s\n",
2494 			options.mac_updating ? "enabled" : "disabled");
2495 
2496 	/* create the mbuf pool */
2497 	l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 512,
2498 			sizeof(struct rte_crypto_op),
2499 			RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
2500 	if (l2fwd_pktmbuf_pool == NULL)
2501 		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
2502 
2503 	/* create crypto op pool */
2504 	l2fwd_crypto_op_pool = rte_crypto_op_pool_create("crypto_op_pool",
2505 			RTE_CRYPTO_OP_TYPE_SYMMETRIC, NB_MBUF, 128, MAXIMUM_IV_LENGTH,
2506 			rte_socket_id());
2507 	if (l2fwd_crypto_op_pool == NULL)
2508 		rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n");
2509 
2510 	/* Enable Ethernet ports */
2511 	enabled_portcount = initialize_ports(&options);
2512 	if (enabled_portcount < 1)
2513 		rte_exit(EXIT_FAILURE, "Failed to initial Ethernet ports\n");
2514 
2515 	nb_ports = rte_eth_dev_count();
2516 	/* Initialize the port/queue configuration of each logical core */
2517 	for (rx_lcore_id = 0, qconf = NULL, portid = 0;
2518 			portid < nb_ports; portid++) {
2519 
2520 		/* skip ports that are not enabled */
2521 		if ((options.portmask & (1 << portid)) == 0)
2522 			continue;
2523 
2524 		if (options.single_lcore && qconf == NULL) {
2525 			while (rte_lcore_is_enabled(rx_lcore_id) == 0) {
2526 				rx_lcore_id++;
2527 				if (rx_lcore_id >= RTE_MAX_LCORE)
2528 					rte_exit(EXIT_FAILURE,
2529 							"Not enough cores\n");
2530 			}
2531 		} else if (!options.single_lcore) {
2532 			/* get the lcore_id for this port */
2533 			while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
2534 			       lcore_queue_conf[rx_lcore_id].nb_rx_ports ==
2535 			       options.nb_ports_per_lcore) {
2536 				rx_lcore_id++;
2537 				if (rx_lcore_id >= RTE_MAX_LCORE)
2538 					rte_exit(EXIT_FAILURE,
2539 							"Not enough cores\n");
2540 			}
2541 		}
2542 
2543 		/* Assigned a new logical core in the loop above. */
2544 		if (qconf != &lcore_queue_conf[rx_lcore_id])
2545 			qconf = &lcore_queue_conf[rx_lcore_id];
2546 
2547 		qconf->rx_port_list[qconf->nb_rx_ports] = portid;
2548 		qconf->nb_rx_ports++;
2549 
2550 		printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned)portid);
2551 	}
2552 
2553 	/* Enable Crypto devices */
2554 	enabled_cdevcount = initialize_cryptodevs(&options, enabled_portcount,
2555 			enabled_cdevs);
2556 	if (enabled_cdevcount < 0)
2557 		rte_exit(EXIT_FAILURE, "Failed to initialize crypto devices\n");
2558 
2559 	if (enabled_cdevcount < enabled_portcount)
2560 		rte_exit(EXIT_FAILURE, "Number of capable crypto devices (%d) "
2561 				"has to be more or equal to number of ports (%d)\n",
2562 				enabled_cdevcount, enabled_portcount);
2563 
2564 	nb_cryptodevs = rte_cryptodev_count();
2565 
2566 	/* Initialize the port/cryptodev configuration of each logical core */
2567 	for (rx_lcore_id = 0, qconf = NULL, cdev_id = 0;
2568 			cdev_id < nb_cryptodevs && enabled_cdevcount;
2569 			cdev_id++) {
2570 		/* Crypto op not supported by crypto device */
2571 		if (!enabled_cdevs[cdev_id])
2572 			continue;
2573 
2574 		if (options.single_lcore && qconf == NULL) {
2575 			while (rte_lcore_is_enabled(rx_lcore_id) == 0) {
2576 				rx_lcore_id++;
2577 				if (rx_lcore_id >= RTE_MAX_LCORE)
2578 					rte_exit(EXIT_FAILURE,
2579 							"Not enough cores\n");
2580 			}
2581 		} else if (!options.single_lcore) {
2582 			/* get the lcore_id for this port */
2583 			while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
2584 			       lcore_queue_conf[rx_lcore_id].nb_crypto_devs ==
2585 			       options.nb_ports_per_lcore) {
2586 				rx_lcore_id++;
2587 				if (rx_lcore_id >= RTE_MAX_LCORE)
2588 					rte_exit(EXIT_FAILURE,
2589 							"Not enough cores\n");
2590 			}
2591 		}
2592 
2593 		/* Assigned a new logical core in the loop above. */
2594 		if (qconf != &lcore_queue_conf[rx_lcore_id])
2595 			qconf = &lcore_queue_conf[rx_lcore_id];
2596 
2597 		qconf->cryptodev_list[qconf->nb_crypto_devs] = cdev_id;
2598 		qconf->nb_crypto_devs++;
2599 
2600 		enabled_cdevcount--;
2601 
2602 		printf("Lcore %u: cryptodev %u\n", rx_lcore_id,
2603 				(unsigned)cdev_id);
2604 	}
2605 
2606 	/* launch per-lcore init on every lcore */
2607 	rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, (void *)&options,
2608 			CALL_MASTER);
2609 	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
2610 		if (rte_eal_wait_lcore(lcore_id) < 0)
2611 			return -1;
2612 	}
2613 
2614 	return 0;
2615 }
2616