xref: /dpdk/examples/l2fwd-crypto/main.c (revision d29ea843932f91a1affbd7faffae99aeaf72c991)
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 
49 #include <rte_atomic.h>
50 #include <rte_branch_prediction.h>
51 #include <rte_common.h>
52 #include <rte_cryptodev.h>
53 #include <rte_cycles.h>
54 #include <rte_debug.h>
55 #include <rte_eal.h>
56 #include <rte_ether.h>
57 #include <rte_ethdev.h>
58 #include <rte_interrupts.h>
59 #include <rte_ip.h>
60 #include <rte_launch.h>
61 #include <rte_lcore.h>
62 #include <rte_log.h>
63 #include <rte_malloc.h>
64 #include <rte_mbuf.h>
65 #include <rte_memcpy.h>
66 #include <rte_memory.h>
67 #include <rte_mempool.h>
68 #include <rte_memzone.h>
69 #include <rte_pci.h>
70 #include <rte_per_lcore.h>
71 #include <rte_prefetch.h>
72 #include <rte_random.h>
73 #include <rte_ring.h>
74 
75 enum cdev_type {
76 	CDEV_TYPE_ANY,
77 	CDEV_TYPE_HW,
78 	CDEV_TYPE_SW
79 };
80 
81 #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
82 
83 #define NB_MBUF   8192
84 
85 #define MAX_STR_LEN 32
86 #define MAX_KEY_SIZE 128
87 #define MAX_PKT_BURST 32
88 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
89 
90 /*
91  * Configurable number of RX/TX ring descriptors
92  */
93 #define RTE_TEST_RX_DESC_DEFAULT 128
94 #define RTE_TEST_TX_DESC_DEFAULT 512
95 
96 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
97 static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
98 
99 /* ethernet addresses of ports */
100 static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
101 
102 /* mask of enabled ports */
103 static uint64_t l2fwd_enabled_port_mask;
104 static uint64_t l2fwd_enabled_crypto_mask;
105 
106 /* list of enabled ports */
107 static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];
108 
109 
110 struct pkt_buffer {
111 	unsigned len;
112 	struct rte_mbuf *buffer[MAX_PKT_BURST];
113 };
114 
115 struct op_buffer {
116 	unsigned len;
117 	struct rte_crypto_op *buffer[MAX_PKT_BURST];
118 };
119 
120 #define MAX_RX_QUEUE_PER_LCORE 16
121 #define MAX_TX_QUEUE_PER_PORT 16
122 
123 enum l2fwd_crypto_xform_chain {
124 	L2FWD_CRYPTO_CIPHER_HASH,
125 	L2FWD_CRYPTO_HASH_CIPHER,
126 	L2FWD_CRYPTO_CIPHER_ONLY,
127 	L2FWD_CRYPTO_HASH_ONLY
128 };
129 
130 struct l2fwd_key {
131 	uint8_t *data;
132 	uint32_t length;
133 	phys_addr_t phys_addr;
134 };
135 
136 /** l2fwd crypto application command line options */
137 struct l2fwd_crypto_options {
138 	unsigned portmask;
139 	unsigned nb_ports_per_lcore;
140 	unsigned refresh_period;
141 	unsigned single_lcore:1;
142 
143 	enum cdev_type type;
144 	unsigned sessionless:1;
145 
146 	enum l2fwd_crypto_xform_chain xform_chain;
147 
148 	struct rte_crypto_sym_xform cipher_xform;
149 	unsigned ckey_param;
150 
151 	struct l2fwd_key iv;
152 	unsigned iv_param;
153 
154 	struct rte_crypto_sym_xform auth_xform;
155 	uint8_t akey_param;
156 
157 	struct l2fwd_key aad;
158 	unsigned aad_param;
159 
160 	uint16_t block_size;
161 	char string_auth_algo[MAX_STR_LEN];
162 	char string_cipher_algo[MAX_STR_LEN];
163 	char string_type[MAX_STR_LEN];
164 };
165 
166 /** l2fwd crypto lcore params */
167 struct l2fwd_crypto_params {
168 	uint8_t dev_id;
169 	uint8_t qp_id;
170 
171 	unsigned digest_length;
172 	unsigned block_size;
173 
174 	struct l2fwd_key iv;
175 	struct l2fwd_key aad;
176 	struct rte_cryptodev_sym_session *session;
177 
178 	uint8_t do_cipher;
179 	uint8_t do_hash;
180 	uint8_t hash_verify;
181 
182 	enum rte_crypto_cipher_algorithm cipher_algo;
183 	enum rte_crypto_auth_algorithm auth_algo;
184 };
185 
186 /** lcore configuration */
187 struct lcore_queue_conf {
188 	unsigned nb_rx_ports;
189 	unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];
190 
191 	unsigned nb_crypto_devs;
192 	unsigned cryptodev_list[MAX_RX_QUEUE_PER_LCORE];
193 
194 	struct op_buffer op_buf[RTE_MAX_ETHPORTS];
195 	struct pkt_buffer pkt_buf[RTE_MAX_ETHPORTS];
196 } __rte_cache_aligned;
197 
198 struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
199 
200 static const struct rte_eth_conf port_conf = {
201 	.rxmode = {
202 		.mq_mode = ETH_MQ_RX_NONE,
203 		.max_rx_pkt_len = ETHER_MAX_LEN,
204 		.split_hdr_size = 0,
205 		.header_split   = 0, /**< Header Split disabled */
206 		.hw_ip_checksum = 0, /**< IP checksum offload disabled */
207 		.hw_vlan_filter = 0, /**< VLAN filtering disabled */
208 		.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
209 		.hw_strip_crc   = 0, /**< CRC stripped by hardware */
210 	},
211 	.txmode = {
212 		.mq_mode = ETH_MQ_TX_NONE,
213 	},
214 };
215 
216 struct rte_mempool *l2fwd_pktmbuf_pool;
217 struct rte_mempool *l2fwd_crypto_op_pool;
218 
219 /* Per-port statistics struct */
220 struct l2fwd_port_statistics {
221 	uint64_t tx;
222 	uint64_t rx;
223 
224 	uint64_t crypto_enqueued;
225 	uint64_t crypto_dequeued;
226 
227 	uint64_t dropped;
228 } __rte_cache_aligned;
229 
230 struct l2fwd_crypto_statistics {
231 	uint64_t enqueued;
232 	uint64_t dequeued;
233 
234 	uint64_t errors;
235 } __rte_cache_aligned;
236 
237 struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];
238 struct l2fwd_crypto_statistics crypto_statistics[RTE_MAX_ETHPORTS];
239 
240 /* A tsc-based timer responsible for triggering statistics printout */
241 #define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */
242 #define MAX_TIMER_PERIOD 86400UL /* 1 day max */
243 
244 /* default period is 10 seconds */
245 static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000;
246 
247 /* Print out statistics on packets dropped */
248 static void
249 print_stats(void)
250 {
251 	uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;
252 	uint64_t total_packets_enqueued, total_packets_dequeued,
253 		total_packets_errors;
254 	unsigned portid;
255 	uint64_t cdevid;
256 
257 	total_packets_dropped = 0;
258 	total_packets_tx = 0;
259 	total_packets_rx = 0;
260 	total_packets_enqueued = 0;
261 	total_packets_dequeued = 0;
262 	total_packets_errors = 0;
263 
264 	const char clr[] = { 27, '[', '2', 'J', '\0' };
265 	const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
266 
267 		/* Clear screen and move to top left */
268 	printf("%s%s", clr, topLeft);
269 
270 	printf("\nPort statistics ====================================");
271 
272 	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
273 		/* skip disabled ports */
274 		if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
275 			continue;
276 		printf("\nStatistics for port %u ------------------------------"
277 			   "\nPackets sent: %32"PRIu64
278 			   "\nPackets received: %28"PRIu64
279 			   "\nPackets dropped: %29"PRIu64,
280 			   portid,
281 			   port_statistics[portid].tx,
282 			   port_statistics[portid].rx,
283 			   port_statistics[portid].dropped);
284 
285 		total_packets_dropped += port_statistics[portid].dropped;
286 		total_packets_tx += port_statistics[portid].tx;
287 		total_packets_rx += port_statistics[portid].rx;
288 	}
289 	printf("\nCrypto statistics ==================================");
290 
291 	for (cdevid = 0; cdevid < RTE_CRYPTO_MAX_DEVS; cdevid++) {
292 		/* skip disabled ports */
293 		if ((l2fwd_enabled_crypto_mask & (1lu << cdevid)) == 0)
294 			continue;
295 		printf("\nStatistics for cryptodev %"PRIu64
296 				" -------------------------"
297 			   "\nPackets enqueued: %28"PRIu64
298 			   "\nPackets dequeued: %28"PRIu64
299 			   "\nPackets errors: %30"PRIu64,
300 			   cdevid,
301 			   crypto_statistics[cdevid].enqueued,
302 			   crypto_statistics[cdevid].dequeued,
303 			   crypto_statistics[cdevid].errors);
304 
305 		total_packets_enqueued += crypto_statistics[cdevid].enqueued;
306 		total_packets_dequeued += crypto_statistics[cdevid].dequeued;
307 		total_packets_errors += crypto_statistics[cdevid].errors;
308 	}
309 	printf("\nAggregate statistics ==============================="
310 		   "\nTotal packets received: %22"PRIu64
311 		   "\nTotal packets enqueued: %22"PRIu64
312 		   "\nTotal packets dequeued: %22"PRIu64
313 		   "\nTotal packets sent: %26"PRIu64
314 		   "\nTotal packets dropped: %23"PRIu64
315 		   "\nTotal packets crypto errors: %17"PRIu64,
316 		   total_packets_rx,
317 		   total_packets_enqueued,
318 		   total_packets_dequeued,
319 		   total_packets_tx,
320 		   total_packets_dropped,
321 		   total_packets_errors);
322 	printf("\n====================================================\n");
323 }
324 
325 
326 
327 static int
328 l2fwd_crypto_send_burst(struct lcore_queue_conf *qconf, unsigned n,
329 		struct l2fwd_crypto_params *cparams)
330 {
331 	struct rte_crypto_op **op_buffer;
332 	unsigned ret;
333 
334 	op_buffer = (struct rte_crypto_op **)
335 			qconf->op_buf[cparams->dev_id].buffer;
336 
337 	ret = rte_cryptodev_enqueue_burst(cparams->dev_id,
338 			cparams->qp_id,	op_buffer, (uint16_t) n);
339 
340 	crypto_statistics[cparams->dev_id].enqueued += ret;
341 	if (unlikely(ret < n)) {
342 		crypto_statistics[cparams->dev_id].errors += (n - ret);
343 		do {
344 			rte_pktmbuf_free(op_buffer[ret]->sym->m_src);
345 			rte_crypto_op_free(op_buffer[ret]);
346 		} while (++ret < n);
347 	}
348 
349 	return 0;
350 }
351 
352 static int
353 l2fwd_crypto_enqueue(struct rte_crypto_op *op,
354 		struct l2fwd_crypto_params *cparams)
355 {
356 	unsigned lcore_id, len;
357 	struct lcore_queue_conf *qconf;
358 
359 	lcore_id = rte_lcore_id();
360 
361 	qconf = &lcore_queue_conf[lcore_id];
362 	len = qconf->op_buf[cparams->dev_id].len;
363 	qconf->op_buf[cparams->dev_id].buffer[len] = op;
364 	len++;
365 
366 	/* enough ops to be sent */
367 	if (len == MAX_PKT_BURST) {
368 		l2fwd_crypto_send_burst(qconf, MAX_PKT_BURST, cparams);
369 		len = 0;
370 	}
371 
372 	qconf->op_buf[cparams->dev_id].len = len;
373 	return 0;
374 }
375 
376 static int
377 l2fwd_simple_crypto_enqueue(struct rte_mbuf *m,
378 		struct rte_crypto_op *op,
379 		struct l2fwd_crypto_params *cparams)
380 {
381 	struct ether_hdr *eth_hdr;
382 	struct ipv4_hdr *ip_hdr;
383 
384 	unsigned ipdata_offset, pad_len, data_len;
385 	char *padding;
386 
387 	eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *);
388 
389 	if (eth_hdr->ether_type != rte_cpu_to_be_16(ETHER_TYPE_IPv4))
390 		return -1;
391 
392 	ipdata_offset = sizeof(struct ether_hdr);
393 
394 	ip_hdr = (struct ipv4_hdr *)(rte_pktmbuf_mtod(m, char *) +
395 			ipdata_offset);
396 
397 	ipdata_offset += (ip_hdr->version_ihl & IPV4_HDR_IHL_MASK)
398 			* IPV4_IHL_MULTIPLIER;
399 
400 
401 	/* Zero pad data to be crypto'd so it is block aligned */
402 	data_len  = rte_pktmbuf_data_len(m) - ipdata_offset;
403 	pad_len = data_len % cparams->block_size ? cparams->block_size -
404 			(data_len % cparams->block_size) : 0;
405 
406 	if (pad_len) {
407 		padding = rte_pktmbuf_append(m, pad_len);
408 		if (unlikely(!padding))
409 			return -1;
410 
411 		data_len += pad_len;
412 		memset(padding, 0, pad_len);
413 	}
414 
415 	/* Set crypto operation data parameters */
416 	rte_crypto_op_attach_sym_session(op, cparams->session);
417 
418 	if (cparams->do_hash) {
419 		if (!cparams->hash_verify) {
420 			/* Append space for digest to end of packet */
421 			op->sym->auth.digest.data = (uint8_t *)rte_pktmbuf_append(m,
422 				cparams->digest_length);
423 		} else {
424 			op->sym->auth.digest.data = (uint8_t *)rte_pktmbuf_append(m,
425 				cparams->digest_length);
426 		}
427 
428 		op->sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(m,
429 				rte_pktmbuf_pkt_len(m) - cparams->digest_length);
430 		op->sym->auth.digest.length = cparams->digest_length;
431 
432 		/* For SNOW3G algorithms, offset/length must be in bits */
433 		if (cparams->auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2) {
434 			op->sym->auth.data.offset = ipdata_offset << 3;
435 			op->sym->auth.data.length = data_len << 3;
436 		} else {
437 			op->sym->auth.data.offset = ipdata_offset;
438 			op->sym->auth.data.length = data_len;
439 		}
440 
441 		if (cparams->aad.length) {
442 			op->sym->auth.aad.data = cparams->aad.data;
443 			op->sym->auth.aad.phys_addr = cparams->aad.phys_addr;
444 			op->sym->auth.aad.length = cparams->aad.length;
445 		}
446 	}
447 
448 	if (cparams->do_cipher) {
449 		op->sym->cipher.iv.data = cparams->iv.data;
450 		op->sym->cipher.iv.phys_addr = cparams->iv.phys_addr;
451 		op->sym->cipher.iv.length = cparams->iv.length;
452 
453 		/* For SNOW3G algorithms, offset/length must be in bits */
454 		if (cparams->cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2) {
455 			op->sym->cipher.data.offset = ipdata_offset << 3;
456 			if (cparams->do_hash && cparams->hash_verify)
457 				/* Do not cipher the hash tag */
458 				op->sym->cipher.data.length = (data_len -
459 					cparams->digest_length) << 3;
460 			else
461 				op->sym->cipher.data.length = data_len << 3;
462 
463 		} else {
464 			op->sym->cipher.data.offset = ipdata_offset;
465 			if (cparams->do_hash && cparams->hash_verify)
466 				/* Do not cipher the hash tag */
467 				op->sym->cipher.data.length = data_len -
468 					cparams->digest_length;
469 			else
470 				op->sym->cipher.data.length = data_len;
471 		}
472 	}
473 
474 	op->sym->m_src = m;
475 
476 	return l2fwd_crypto_enqueue(op, cparams);
477 }
478 
479 
480 /* Send the burst of packets on an output interface */
481 static int
482 l2fwd_send_burst(struct lcore_queue_conf *qconf, unsigned n,
483 		uint8_t port)
484 {
485 	struct rte_mbuf **pkt_buffer;
486 	unsigned ret;
487 
488 	pkt_buffer = (struct rte_mbuf **)qconf->pkt_buf[port].buffer;
489 
490 	ret = rte_eth_tx_burst(port, 0, pkt_buffer, (uint16_t)n);
491 	port_statistics[port].tx += ret;
492 	if (unlikely(ret < n)) {
493 		port_statistics[port].dropped += (n - ret);
494 		do {
495 			rte_pktmbuf_free(pkt_buffer[ret]);
496 		} while (++ret < n);
497 	}
498 
499 	return 0;
500 }
501 
502 /* Enqueue packets for TX and prepare them to be sent */
503 static int
504 l2fwd_send_packet(struct rte_mbuf *m, uint8_t port)
505 {
506 	unsigned lcore_id, len;
507 	struct lcore_queue_conf *qconf;
508 
509 	lcore_id = rte_lcore_id();
510 
511 	qconf = &lcore_queue_conf[lcore_id];
512 	len = qconf->pkt_buf[port].len;
513 	qconf->pkt_buf[port].buffer[len] = m;
514 	len++;
515 
516 	/* enough pkts to be sent */
517 	if (unlikely(len == MAX_PKT_BURST)) {
518 		l2fwd_send_burst(qconf, MAX_PKT_BURST, port);
519 		len = 0;
520 	}
521 
522 	qconf->pkt_buf[port].len = len;
523 	return 0;
524 }
525 
526 static void
527 l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid)
528 {
529 	struct ether_hdr *eth;
530 	void *tmp;
531 	unsigned dst_port;
532 
533 	dst_port = l2fwd_dst_ports[portid];
534 	eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
535 
536 	/* 02:00:00:00:00:xx */
537 	tmp = &eth->d_addr.addr_bytes[0];
538 	*((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40);
539 
540 	/* src addr */
541 	ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], &eth->s_addr);
542 
543 	l2fwd_send_packet(m, (uint8_t) dst_port);
544 }
545 
546 /** Generate random key */
547 static void
548 generate_random_key(uint8_t *key, unsigned length)
549 {
550 	unsigned i;
551 
552 	for (i = 0; i < length; i++)
553 		key[i] = rand() % 0xff;
554 }
555 
556 static struct rte_cryptodev_sym_session *
557 initialize_crypto_session(struct l2fwd_crypto_options *options,
558 		uint8_t cdev_id)
559 {
560 	struct rte_crypto_sym_xform *first_xform;
561 
562 	if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH) {
563 		first_xform = &options->cipher_xform;
564 		first_xform->next = &options->auth_xform;
565 	} else if (options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER) {
566 		first_xform = &options->auth_xform;
567 		first_xform->next = &options->cipher_xform;
568 	} else if (options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
569 		first_xform = &options->cipher_xform;
570 	} else {
571 		first_xform = &options->auth_xform;
572 	}
573 
574 	/* Setup Cipher Parameters */
575 	return rte_cryptodev_sym_session_create(cdev_id, first_xform);
576 }
577 
578 static void
579 l2fwd_crypto_options_print(struct l2fwd_crypto_options *options);
580 
581 /* main processing loop */
582 static void
583 l2fwd_main_loop(struct l2fwd_crypto_options *options)
584 {
585 	struct rte_mbuf *m, *pkts_burst[MAX_PKT_BURST];
586 	struct rte_crypto_op *ops_burst[MAX_PKT_BURST];
587 
588 	unsigned lcore_id = rte_lcore_id();
589 	uint64_t prev_tsc = 0, diff_tsc, cur_tsc, timer_tsc = 0;
590 	unsigned i, j, portid, nb_rx;
591 	struct lcore_queue_conf *qconf = &lcore_queue_conf[lcore_id];
592 	const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) /
593 			US_PER_S * BURST_TX_DRAIN_US;
594 	struct l2fwd_crypto_params *cparams;
595 	struct l2fwd_crypto_params port_cparams[qconf->nb_crypto_devs];
596 
597 	if (qconf->nb_rx_ports == 0) {
598 		RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id);
599 		return;
600 	}
601 
602 	RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);
603 
604 	l2fwd_crypto_options_print(options);
605 
606 	for (i = 0; i < qconf->nb_rx_ports; i++) {
607 
608 		portid = qconf->rx_port_list[i];
609 		RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,
610 			portid);
611 	}
612 
613 	for (i = 0; i < qconf->nb_crypto_devs; i++) {
614 		port_cparams[i].do_cipher = 0;
615 		port_cparams[i].do_hash = 0;
616 
617 		switch (options->xform_chain) {
618 		case L2FWD_CRYPTO_CIPHER_HASH:
619 		case L2FWD_CRYPTO_HASH_CIPHER:
620 			port_cparams[i].do_cipher = 1;
621 			port_cparams[i].do_hash = 1;
622 			break;
623 		case L2FWD_CRYPTO_HASH_ONLY:
624 			port_cparams[i].do_hash = 1;
625 			break;
626 		case L2FWD_CRYPTO_CIPHER_ONLY:
627 			port_cparams[i].do_cipher = 1;
628 			break;
629 		}
630 
631 		port_cparams[i].dev_id = qconf->cryptodev_list[i];
632 		port_cparams[i].qp_id = 0;
633 
634 		port_cparams[i].block_size = options->block_size;
635 
636 		if (port_cparams[i].do_hash) {
637 			port_cparams[i].digest_length =
638 					options->auth_xform.auth.digest_length;
639 			if (options->auth_xform.auth.add_auth_data_length) {
640 				port_cparams[i].aad.data = options->aad.data;
641 				port_cparams[i].aad.length =
642 					options->auth_xform.auth.add_auth_data_length;
643 				port_cparams[i].aad.phys_addr = options->aad.phys_addr;
644 				if (!options->aad_param)
645 					generate_random_key(port_cparams[i].aad.data,
646 						sizeof(port_cparams[i].aad.length));
647 
648 			}
649 
650 			if (options->auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY)
651 				port_cparams[i].hash_verify = 1;
652 			else
653 				port_cparams[i].hash_verify = 0;
654 
655 			port_cparams[i].auth_algo = options->auth_xform.auth.algo;
656 		}
657 
658 		if (port_cparams[i].do_cipher) {
659 			port_cparams[i].iv.data = options->iv.data;
660 			port_cparams[i].iv.length = options->iv.length;
661 			port_cparams[i].iv.phys_addr = options->iv.phys_addr;
662 			if (!options->iv_param)
663 				generate_random_key(port_cparams[i].iv.data,
664 						sizeof(port_cparams[i].iv.length));
665 
666 			port_cparams[i].cipher_algo = options->cipher_xform.cipher.algo;
667 		}
668 
669 		port_cparams[i].session = initialize_crypto_session(options,
670 				port_cparams[i].dev_id);
671 
672 		if (port_cparams[i].session == NULL)
673 			return;
674 		RTE_LOG(INFO, L2FWD, " -- lcoreid=%u cryptoid=%u\n", lcore_id,
675 				port_cparams[i].dev_id);
676 	}
677 
678 	while (1) {
679 
680 		cur_tsc = rte_rdtsc();
681 
682 		/*
683 		 * TX burst queue drain
684 		 */
685 		diff_tsc = cur_tsc - prev_tsc;
686 		if (unlikely(diff_tsc > drain_tsc)) {
687 			for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
688 				if (qconf->pkt_buf[portid].len == 0)
689 					continue;
690 				l2fwd_send_burst(&lcore_queue_conf[lcore_id],
691 						 qconf->pkt_buf[portid].len,
692 						 (uint8_t) portid);
693 				qconf->pkt_buf[portid].len = 0;
694 			}
695 
696 			/* if timer is enabled */
697 			if (timer_period > 0) {
698 
699 				/* advance the timer */
700 				timer_tsc += diff_tsc;
701 
702 				/* if timer has reached its timeout */
703 				if (unlikely(timer_tsc >=
704 						(uint64_t)timer_period)) {
705 
706 					/* do this only on master core */
707 					if (lcore_id == rte_get_master_lcore()
708 						&& options->refresh_period) {
709 						print_stats();
710 						timer_tsc = 0;
711 					}
712 				}
713 			}
714 
715 			prev_tsc = cur_tsc;
716 		}
717 
718 		/*
719 		 * Read packet from RX queues
720 		 */
721 		for (i = 0; i < qconf->nb_rx_ports; i++) {
722 			portid = qconf->rx_port_list[i];
723 
724 			cparams = &port_cparams[i];
725 
726 			nb_rx = rte_eth_rx_burst((uint8_t) portid, 0,
727 						 pkts_burst, MAX_PKT_BURST);
728 
729 			port_statistics[portid].rx += nb_rx;
730 
731 			if (nb_rx) {
732 				/*
733 				 * If we can't allocate a crypto_ops, then drop
734 				 * the rest of the burst and dequeue and
735 				 * process the packets to free offload structs
736 				 */
737 				if (rte_crypto_op_bulk_alloc(
738 						l2fwd_crypto_op_pool,
739 						RTE_CRYPTO_OP_TYPE_SYMMETRIC,
740 						ops_burst, nb_rx) !=
741 								nb_rx) {
742 					for (j = 0; j < nb_rx; j++)
743 						rte_pktmbuf_free(pkts_burst[i]);
744 
745 					nb_rx = 0;
746 				}
747 
748 				/* Enqueue packets from Crypto device*/
749 				for (j = 0; j < nb_rx; j++) {
750 					m = pkts_burst[j];
751 
752 					l2fwd_simple_crypto_enqueue(m,
753 							ops_burst[j], cparams);
754 				}
755 			}
756 
757 			/* Dequeue packets from Crypto device */
758 			do {
759 				nb_rx = rte_cryptodev_dequeue_burst(
760 						cparams->dev_id, cparams->qp_id,
761 						ops_burst, MAX_PKT_BURST);
762 
763 				crypto_statistics[cparams->dev_id].dequeued +=
764 						nb_rx;
765 
766 				/* Forward crypto'd packets */
767 				for (j = 0; j < nb_rx; j++) {
768 					m = ops_burst[j]->sym->m_src;
769 
770 					rte_crypto_op_free(ops_burst[j]);
771 					l2fwd_simple_forward(m, portid);
772 				}
773 			} while (nb_rx == MAX_PKT_BURST);
774 		}
775 	}
776 }
777 
778 static int
779 l2fwd_launch_one_lcore(void *arg)
780 {
781 	l2fwd_main_loop((struct l2fwd_crypto_options *)arg);
782 	return 0;
783 }
784 
785 /* Display command line arguments usage */
786 static void
787 l2fwd_crypto_usage(const char *prgname)
788 {
789 	printf("%s [EAL options] --\n"
790 		"  -p PORTMASK: hexadecimal bitmask of ports to configure\n"
791 		"  -q NQ: number of queue (=ports) per lcore (default is 1)\n"
792 		"  -s manage all ports from single lcore"
793 		"  -t PERIOD: statistics will be refreshed each PERIOD seconds"
794 		" (0 to disable, 10 default, 86400 maximum)\n"
795 
796 		"  --cdev_type HW / SW / ANY\n"
797 		"  --chain HASH_CIPHER / CIPHER_HASH\n"
798 
799 		"  --cipher_algo ALGO\n"
800 		"  --cipher_op ENCRYPT / DECRYPT\n"
801 		"  --cipher_key KEY\n"
802 		"  --iv IV\n"
803 
804 		"  --auth_algo ALGO\n"
805 		"  --auth_op GENERATE / VERIFY\n"
806 		"  --auth_key KEY\n"
807 		"  --aad AAD\n"
808 
809 		"  --sessionless\n",
810 	       prgname);
811 }
812 
813 /** Parse crypto device type command line argument */
814 static int
815 parse_cryptodev_type(enum cdev_type *type, char *optarg)
816 {
817 	if (strcmp("HW", optarg) == 0) {
818 		*type = CDEV_TYPE_HW;
819 		return 0;
820 	} else if (strcmp("SW", optarg) == 0) {
821 		*type = CDEV_TYPE_SW;
822 		return 0;
823 	} else if (strcmp("ANY", optarg) == 0) {
824 		*type = CDEV_TYPE_ANY;
825 		return 0;
826 	}
827 
828 	return -1;
829 }
830 
831 /** Parse crypto chain xform command line argument */
832 static int
833 parse_crypto_opt_chain(struct l2fwd_crypto_options *options, char *optarg)
834 {
835 	if (strcmp("CIPHER_HASH", optarg) == 0) {
836 		options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;
837 		return 0;
838 	} else if (strcmp("HASH_CIPHER", optarg) == 0) {
839 		options->xform_chain = L2FWD_CRYPTO_HASH_CIPHER;
840 		return 0;
841 	} else if (strcmp("CIPHER_ONLY", optarg) == 0) {
842 		options->xform_chain = L2FWD_CRYPTO_CIPHER_ONLY;
843 		return 0;
844 	} else if (strcmp("HASH_ONLY", optarg) == 0) {
845 		options->xform_chain = L2FWD_CRYPTO_HASH_ONLY;
846 		return 0;
847 	}
848 
849 	return -1;
850 }
851 
852 /** Parse crypto cipher algo option command line argument */
853 static int
854 parse_cipher_algo(enum rte_crypto_cipher_algorithm *algo, char *optarg)
855 {
856 	if (strcmp("AES_CBC", optarg) == 0) {
857 		*algo = RTE_CRYPTO_CIPHER_AES_CBC;
858 		return 0;
859 	} else if (strcmp("AES_GCM", optarg) == 0) {
860 		*algo = RTE_CRYPTO_CIPHER_AES_GCM;
861 		return 0;
862 	} else if (strcmp("SNOW3G_UEA2", optarg) == 0) {
863 		*algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
864 		return 0;
865 	}
866 
867 	printf("Cipher algorithm  not supported!\n");
868 	return -1;
869 }
870 
871 /** Parse crypto cipher operation command line argument */
872 static int
873 parse_cipher_op(enum rte_crypto_cipher_operation *op, char *optarg)
874 {
875 	if (strcmp("ENCRYPT", optarg) == 0) {
876 		*op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
877 		return 0;
878 	} else if (strcmp("DECRYPT", optarg) == 0) {
879 		*op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
880 		return 0;
881 	}
882 
883 	printf("Cipher operation not supported!\n");
884 	return -1;
885 }
886 
887 /** Parse crypto key command line argument */
888 static int
889 parse_key(uint8_t *data, char *input_arg)
890 {
891 	unsigned byte_count;
892 	char *token;
893 
894 	for (byte_count = 0, token = strtok(input_arg, ":");
895 			(byte_count < MAX_KEY_SIZE) && (token != NULL);
896 			token = strtok(NULL, ":")) {
897 
898 		int number = (int)strtol(token, NULL, 16);
899 
900 		if (errno == EINVAL || errno == ERANGE || number > 0xFF)
901 			return -1;
902 
903 		data[byte_count++] = (uint8_t)number;
904 	}
905 
906 	return 0;
907 }
908 
909 /** Parse crypto cipher operation command line argument */
910 static int
911 parse_auth_algo(enum rte_crypto_auth_algorithm *algo, char *optarg)
912 {
913 	if (strcmp("MD5_HMAC", optarg) == 0) {
914 		*algo = RTE_CRYPTO_AUTH_MD5_HMAC;
915 		return 0;
916 	} else if (strcmp("SHA1_HMAC", optarg) == 0) {
917 		*algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
918 		return 0;
919 	} else if (strcmp("SHA224_HMAC", optarg) == 0) {
920 		*algo = RTE_CRYPTO_AUTH_SHA224_HMAC;
921 		return 0;
922 	} else if (strcmp("SHA256_HMAC", optarg) == 0) {
923 		*algo = RTE_CRYPTO_AUTH_SHA256_HMAC;
924 		return 0;
925 	}  else if (strcmp("SHA384_HMAC", optarg) == 0) {
926 		*algo = RTE_CRYPTO_AUTH_SHA384_HMAC;
927 		return 0;
928 	} else if (strcmp("SHA512_HMAC", optarg) == 0) {
929 		*algo = RTE_CRYPTO_AUTH_SHA512_HMAC;
930 		return 0;
931 	} else if (strcmp("SNOW3G_UIA2", optarg) == 0) {
932 		*algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2;
933 		return 0;
934 	}
935 
936 	printf("Authentication algorithm specified not supported!\n");
937 	return -1;
938 }
939 
940 static int
941 parse_auth_op(enum rte_crypto_auth_operation *op, char *optarg)
942 {
943 	if (strcmp("VERIFY", optarg) == 0) {
944 		*op = RTE_CRYPTO_AUTH_OP_VERIFY;
945 		return 0;
946 	} else if (strcmp("GENERATE", optarg) == 0) {
947 		*op = RTE_CRYPTO_AUTH_OP_GENERATE;
948 		return 0;
949 	}
950 
951 	printf("Authentication operation specified not supported!\n");
952 	return -1;
953 }
954 
955 /** Parse long options */
956 static int
957 l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,
958 		struct option *lgopts, int option_index)
959 {
960 	int retval;
961 
962 	if (strcmp(lgopts[option_index].name, "cdev_type") == 0)
963 		return parse_cryptodev_type(&options->type, optarg);
964 
965 	else if (strcmp(lgopts[option_index].name, "chain") == 0)
966 		return parse_crypto_opt_chain(options, optarg);
967 
968 	/* Cipher options */
969 	else if (strcmp(lgopts[option_index].name, "cipher_algo") == 0) {
970 		retval = parse_cipher_algo(&options->cipher_xform.cipher.algo,
971 				optarg);
972 		if (retval == 0)
973 			strcpy(options->string_cipher_algo, optarg);
974 		return retval;
975 	}
976 
977 	else if (strcmp(lgopts[option_index].name, "cipher_op") == 0)
978 		return parse_cipher_op(&options->cipher_xform.cipher.op,
979 				optarg);
980 
981 	else if (strcmp(lgopts[option_index].name, "cipher_key") == 0) {
982 		options->ckey_param = 1;
983 		return parse_key(options->cipher_xform.cipher.key.data, optarg);
984 	}
985 
986 	else if (strcmp(lgopts[option_index].name, "iv") == 0) {
987 		options->iv_param = 1;
988 		return parse_key(options->iv.data, optarg);
989 	}
990 
991 	/* Authentication options */
992 	else if (strcmp(lgopts[option_index].name, "auth_algo") == 0) {
993 		retval = parse_auth_algo(&options->auth_xform.auth.algo,
994 				optarg);
995 		if (retval == 0)
996 			strcpy(options->string_auth_algo, optarg);
997 		return retval;
998 	}
999 
1000 	else if (strcmp(lgopts[option_index].name, "auth_op") == 0)
1001 		return parse_auth_op(&options->auth_xform.auth.op,
1002 				optarg);
1003 
1004 	else if (strcmp(lgopts[option_index].name, "auth_key") == 0) {
1005 		options->akey_param = 1;
1006 		return parse_key(options->auth_xform.auth.key.data, optarg);
1007 	}
1008 
1009 	else if (strcmp(lgopts[option_index].name, "aad") == 0) {
1010 		options->aad_param = 1;
1011 		return parse_key(options->aad.data, optarg);
1012 	}
1013 
1014 	else if (strcmp(lgopts[option_index].name, "sessionless") == 0) {
1015 		options->sessionless = 1;
1016 		return 0;
1017 	}
1018 
1019 	return -1;
1020 }
1021 
1022 /** Parse port mask */
1023 static int
1024 l2fwd_crypto_parse_portmask(struct l2fwd_crypto_options *options,
1025 		const char *q_arg)
1026 {
1027 	char *end = NULL;
1028 	unsigned long pm;
1029 
1030 	/* parse hexadecimal string */
1031 	pm = strtoul(q_arg, &end, 16);
1032 	if ((pm == '\0') || (end == NULL) || (*end != '\0'))
1033 		pm = 0;
1034 
1035 	options->portmask = pm;
1036 	if (options->portmask == 0) {
1037 		printf("invalid portmask specified\n");
1038 		return -1;
1039 	}
1040 
1041 	return pm;
1042 }
1043 
1044 /** Parse number of queues */
1045 static int
1046 l2fwd_crypto_parse_nqueue(struct l2fwd_crypto_options *options,
1047 		const char *q_arg)
1048 {
1049 	char *end = NULL;
1050 	unsigned long n;
1051 
1052 	/* parse hexadecimal string */
1053 	n = strtoul(q_arg, &end, 10);
1054 	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1055 		n = 0;
1056 	else if (n >= MAX_RX_QUEUE_PER_LCORE)
1057 		n = 0;
1058 
1059 	options->nb_ports_per_lcore = n;
1060 	if (options->nb_ports_per_lcore == 0) {
1061 		printf("invalid number of ports selected\n");
1062 		return -1;
1063 	}
1064 
1065 	return 0;
1066 }
1067 
1068 /** Parse timer period */
1069 static int
1070 l2fwd_crypto_parse_timer_period(struct l2fwd_crypto_options *options,
1071 		const char *q_arg)
1072 {
1073 	char *end = NULL;
1074 	unsigned long n;
1075 
1076 	/* parse number string */
1077 	n = (unsigned)strtol(q_arg, &end, 10);
1078 	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1079 		n = 0;
1080 
1081 	if (n >= MAX_TIMER_PERIOD) {
1082 		printf("Warning refresh period specified %lu is greater than "
1083 				"max value %lu! using max value",
1084 				n, MAX_TIMER_PERIOD);
1085 		n = MAX_TIMER_PERIOD;
1086 	}
1087 
1088 	options->refresh_period = n * 1000 * TIMER_MILLISECOND;
1089 
1090 	return 0;
1091 }
1092 
1093 /** Generate default options for application */
1094 static void
1095 l2fwd_crypto_default_options(struct l2fwd_crypto_options *options)
1096 {
1097 	srand(time(NULL));
1098 
1099 	options->portmask = 0xffffffff;
1100 	options->nb_ports_per_lcore = 1;
1101 	options->refresh_period = 10000;
1102 	options->single_lcore = 0;
1103 	options->sessionless = 0;
1104 
1105 	options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;
1106 
1107 	/* Cipher Data */
1108 	options->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1109 	options->cipher_xform.next = NULL;
1110 	options->ckey_param = 0;
1111 	options->iv_param = 0;
1112 
1113 	options->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
1114 	options->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
1115 
1116 	/* Authentication Data */
1117 	options->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
1118 	options->auth_xform.next = NULL;
1119 	options->akey_param = 0;
1120 	options->aad_param = 0;
1121 
1122 	options->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
1123 	options->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
1124 
1125 	options->type = CDEV_TYPE_ANY;
1126 }
1127 
1128 static void
1129 l2fwd_crypto_options_print(struct l2fwd_crypto_options *options)
1130 {
1131 	printf("Options:-\nn");
1132 	printf("portmask: %x\n", options->portmask);
1133 	printf("ports per lcore: %u\n", options->nb_ports_per_lcore);
1134 	printf("refresh period : %u\n", options->refresh_period);
1135 	printf("single lcore mode: %s\n",
1136 			options->single_lcore ? "enabled" : "disabled");
1137 	printf("stats_printing: %s\n",
1138 			options->refresh_period == 0 ? "disabled" : "enabled");
1139 
1140 	printf("sessionless crypto: %s\n",
1141 			options->sessionless ? "enabled" : "disabled");
1142 }
1143 
1144 /* Parse the argument given in the command line of the application */
1145 static int
1146 l2fwd_crypto_parse_args(struct l2fwd_crypto_options *options,
1147 		int argc, char **argv)
1148 {
1149 	int opt, retval, option_index;
1150 	char **argvopt = argv, *prgname = argv[0];
1151 
1152 	static struct option lgopts[] = {
1153 			{ "sessionless", no_argument, 0, 0 },
1154 
1155 			{ "cdev_type", required_argument, 0, 0 },
1156 			{ "chain", required_argument, 0, 0 },
1157 
1158 			{ "cipher_algo", required_argument, 0, 0 },
1159 			{ "cipher_op", required_argument, 0, 0 },
1160 			{ "cipher_key", required_argument, 0, 0 },
1161 
1162 			{ "auth_algo", required_argument, 0, 0 },
1163 			{ "auth_op", required_argument, 0, 0 },
1164 			{ "auth_key", required_argument, 0, 0 },
1165 
1166 			{ "iv", required_argument, 0, 0 },
1167 			{ "aad", required_argument, 0, 0 },
1168 
1169 			{ "sessionless", no_argument, 0, 0 },
1170 
1171 			{ NULL, 0, 0, 0 }
1172 	};
1173 
1174 	l2fwd_crypto_default_options(options);
1175 
1176 	while ((opt = getopt_long(argc, argvopt, "p:q:st:", lgopts,
1177 			&option_index)) != EOF) {
1178 		switch (opt) {
1179 		/* long options */
1180 		case 0:
1181 			retval = l2fwd_crypto_parse_args_long_options(options,
1182 					lgopts, option_index);
1183 			if (retval < 0) {
1184 				l2fwd_crypto_usage(prgname);
1185 				return -1;
1186 			}
1187 			break;
1188 
1189 		/* portmask */
1190 		case 'p':
1191 			retval = l2fwd_crypto_parse_portmask(options, optarg);
1192 			if (retval < 0) {
1193 				l2fwd_crypto_usage(prgname);
1194 				return -1;
1195 			}
1196 			break;
1197 
1198 		/* nqueue */
1199 		case 'q':
1200 			retval = l2fwd_crypto_parse_nqueue(options, optarg);
1201 			if (retval < 0) {
1202 				l2fwd_crypto_usage(prgname);
1203 				return -1;
1204 			}
1205 			break;
1206 
1207 		/* single  */
1208 		case 's':
1209 			options->single_lcore = 1;
1210 
1211 			break;
1212 
1213 		/* timer period */
1214 		case 't':
1215 			retval = l2fwd_crypto_parse_timer_period(options,
1216 					optarg);
1217 			if (retval < 0) {
1218 				l2fwd_crypto_usage(prgname);
1219 				return -1;
1220 			}
1221 			break;
1222 
1223 		default:
1224 			l2fwd_crypto_usage(prgname);
1225 			return -1;
1226 		}
1227 	}
1228 
1229 
1230 	if (optind >= 0)
1231 		argv[optind-1] = prgname;
1232 
1233 	retval = optind-1;
1234 	optind = 0; /* reset getopt lib */
1235 
1236 	return retval;
1237 }
1238 
1239 /* Check the link status of all ports in up to 9s, and print them finally */
1240 static void
1241 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
1242 {
1243 #define CHECK_INTERVAL 100 /* 100ms */
1244 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
1245 	uint8_t portid, count, all_ports_up, print_flag = 0;
1246 	struct rte_eth_link link;
1247 
1248 	printf("\nChecking link status");
1249 	fflush(stdout);
1250 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
1251 		all_ports_up = 1;
1252 		for (portid = 0; portid < port_num; portid++) {
1253 			if ((port_mask & (1 << portid)) == 0)
1254 				continue;
1255 			memset(&link, 0, sizeof(link));
1256 			rte_eth_link_get_nowait(portid, &link);
1257 			/* print link status if flag set */
1258 			if (print_flag == 1) {
1259 				if (link.link_status)
1260 					printf("Port %d Link Up - speed %u "
1261 						"Mbps - %s\n", (uint8_t)portid,
1262 						(unsigned)link.link_speed,
1263 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
1264 					("full-duplex") : ("half-duplex\n"));
1265 				else
1266 					printf("Port %d Link Down\n",
1267 						(uint8_t)portid);
1268 				continue;
1269 			}
1270 			/* clear all_ports_up flag if any link down */
1271 			if (link.link_status == 0) {
1272 				all_ports_up = 0;
1273 				break;
1274 			}
1275 		}
1276 		/* after finally printing all link status, get out */
1277 		if (print_flag == 1)
1278 			break;
1279 
1280 		if (all_ports_up == 0) {
1281 			printf(".");
1282 			fflush(stdout);
1283 			rte_delay_ms(CHECK_INTERVAL);
1284 		}
1285 
1286 		/* set the print_flag if all ports up or timeout */
1287 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
1288 			print_flag = 1;
1289 			printf("done\n");
1290 		}
1291 	}
1292 }
1293 
1294 /* Check if device has to be HW/SW or any */
1295 static int
1296 check_type(struct l2fwd_crypto_options *options, struct rte_cryptodev_info *dev_info)
1297 {
1298 	if (options->type == CDEV_TYPE_HW &&
1299 			(dev_info->feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED))
1300 		return 0;
1301 	if (options->type == CDEV_TYPE_SW &&
1302 			!(dev_info->feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED))
1303 		return 0;
1304 	if (options->type == CDEV_TYPE_ANY)
1305 		return 0;
1306 
1307 	return -1;
1308 }
1309 
1310 static int
1311 initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports,
1312 		uint8_t *enabled_cdevs)
1313 {
1314 	unsigned i, cdev_id, cdev_count, enabled_cdev_count = 0;
1315 	const struct rte_cryptodev_capabilities *cap;
1316 	enum rte_crypto_auth_algorithm cap_auth_algo;
1317 	enum rte_crypto_auth_algorithm opt_auth_algo;
1318 	enum rte_crypto_cipher_algorithm cap_cipher_algo;
1319 	enum rte_crypto_cipher_algorithm opt_cipher_algo;
1320 	int retval;
1321 
1322 	cdev_count = rte_cryptodev_count();
1323 	if (cdev_count == 0) {
1324 		printf("No crypto devices available\n");
1325 		return -1;
1326 	}
1327 
1328 	for (cdev_id = 0; cdev_id < cdev_count && enabled_cdev_count < nb_ports;
1329 			cdev_id++) {
1330 		struct rte_cryptodev_qp_conf qp_conf;
1331 		struct rte_cryptodev_info dev_info;
1332 
1333 		struct rte_cryptodev_config conf = {
1334 			.nb_queue_pairs = 1,
1335 			.socket_id = SOCKET_ID_ANY,
1336 			.session_mp = {
1337 				.nb_objs = 2048,
1338 				.cache_size = 64
1339 			}
1340 		};
1341 
1342 		rte_cryptodev_info_get(cdev_id, &dev_info);
1343 
1344 		/* Set cipher parameters */
1345 		if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
1346 				options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
1347 				options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
1348 			/* Check if device supports cipher algo */
1349 			i = 0;
1350 			opt_cipher_algo = options->cipher_xform.cipher.algo;
1351 			cap = &dev_info.capabilities[i];
1352 			while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1353 				cap_cipher_algo = cap->sym.cipher.algo;
1354 				if (cap->sym.xform_type ==
1355 						RTE_CRYPTO_SYM_XFORM_CIPHER) {
1356 					if (cap_cipher_algo == opt_cipher_algo) {
1357 						if (check_type(options, &dev_info) == 0)
1358 							break;
1359 					}
1360 				}
1361 				cap = &dev_info.capabilities[++i];
1362 			}
1363 
1364 			if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1365 				printf("Algorithm %s not supported by cryptodev %u"
1366 					" or device not of preferred type (%s)\n",
1367 					options->string_cipher_algo, cdev_id,
1368 					options->string_type);
1369 				continue;
1370 			}
1371 
1372 			options->block_size = cap->sym.cipher.block_size;
1373 			options->iv.length = cap->sym.cipher.iv_size.min;
1374 			options->cipher_xform.cipher.key.length =
1375 						cap->sym.cipher.key_size.min;
1376 			if (!options->ckey_param)
1377 				generate_random_key(
1378 					options->cipher_xform.cipher.key.data,
1379 					options->cipher_xform.cipher.key.length);
1380 
1381 		}
1382 
1383 		/* Set auth parameters */
1384 		if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
1385 				options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
1386 				options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) {
1387 			/* Check if device supports auth algo */
1388 			i = 0;
1389 			opt_auth_algo = options->auth_xform.auth.algo;
1390 			cap = &dev_info.capabilities[i];
1391 			while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1392 				cap_auth_algo = cap->sym.auth.algo;
1393 				if ((cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AUTH) &&
1394 						(cap_auth_algo == opt_auth_algo) &&
1395 						(check_type(options, &dev_info) == 0)) {
1396 					break;
1397 				}
1398 				cap = &dev_info.capabilities[++i];
1399 			}
1400 
1401 			if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1402 				printf("Algorithm %s not supported by cryptodev %u"
1403 					" or device not of preferred type (%s)\n",
1404 					options->string_auth_algo, cdev_id,
1405 					options->string_type);
1406 				continue;
1407 			}
1408 
1409 			options->block_size = cap->sym.auth.block_size;
1410 			options->auth_xform.auth.add_auth_data_length =
1411 						cap->sym.auth.aad_size.min;
1412 			options->auth_xform.auth.digest_length =
1413 						cap->sym.auth.digest_size.min;
1414 			options->auth_xform.auth.key.length =
1415 						cap->sym.auth.key_size.min;
1416 
1417 			if (!options->akey_param)
1418 				generate_random_key(
1419 					options->auth_xform.auth.key.data,
1420 					options->auth_xform.auth.key.length);
1421 		}
1422 
1423 		retval = rte_cryptodev_configure(cdev_id, &conf);
1424 		if (retval < 0) {
1425 			printf("Failed to configure cryptodev %u", cdev_id);
1426 			return -1;
1427 		}
1428 
1429 		qp_conf.nb_descriptors = 2048;
1430 
1431 		retval = rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
1432 				SOCKET_ID_ANY);
1433 		if (retval < 0) {
1434 			printf("Failed to setup queue pair %u on cryptodev %u",
1435 					0, cdev_id);
1436 			return -1;
1437 		}
1438 
1439 		l2fwd_enabled_crypto_mask |= (1 << cdev_id);
1440 
1441 		enabled_cdevs[cdev_id] = 1;
1442 		enabled_cdev_count++;
1443 	}
1444 
1445 	return enabled_cdev_count;
1446 }
1447 
1448 static int
1449 initialize_ports(struct l2fwd_crypto_options *options)
1450 {
1451 	uint8_t last_portid, portid;
1452 	unsigned enabled_portcount = 0;
1453 	unsigned nb_ports = rte_eth_dev_count();
1454 
1455 	if (nb_ports == 0) {
1456 		printf("No Ethernet ports - bye\n");
1457 		return -1;
1458 	}
1459 
1460 	if (nb_ports > RTE_MAX_ETHPORTS)
1461 		nb_ports = RTE_MAX_ETHPORTS;
1462 
1463 	/* Reset l2fwd_dst_ports */
1464 	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
1465 		l2fwd_dst_ports[portid] = 0;
1466 
1467 	for (last_portid = 0, portid = 0; portid < nb_ports; portid++) {
1468 		int retval;
1469 
1470 		/* Skip ports that are not enabled */
1471 		if ((options->portmask & (1 << portid)) == 0)
1472 			continue;
1473 
1474 		/* init port */
1475 		printf("Initializing port %u... ", (unsigned) portid);
1476 		fflush(stdout);
1477 		retval = rte_eth_dev_configure(portid, 1, 1, &port_conf);
1478 		if (retval < 0) {
1479 			printf("Cannot configure device: err=%d, port=%u\n",
1480 				  retval, (unsigned) portid);
1481 			return -1;
1482 		}
1483 
1484 		/* init one RX queue */
1485 		fflush(stdout);
1486 		retval = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
1487 					     rte_eth_dev_socket_id(portid),
1488 					     NULL, l2fwd_pktmbuf_pool);
1489 		if (retval < 0) {
1490 			printf("rte_eth_rx_queue_setup:err=%d, port=%u\n",
1491 					retval, (unsigned) portid);
1492 			return -1;
1493 		}
1494 
1495 		/* init one TX queue on each port */
1496 		fflush(stdout);
1497 		retval = rte_eth_tx_queue_setup(portid, 0, nb_txd,
1498 				rte_eth_dev_socket_id(portid),
1499 				NULL);
1500 		if (retval < 0) {
1501 			printf("rte_eth_tx_queue_setup:err=%d, port=%u\n",
1502 				retval, (unsigned) portid);
1503 
1504 			return -1;
1505 		}
1506 
1507 		/* Start device */
1508 		retval = rte_eth_dev_start(portid);
1509 		if (retval < 0) {
1510 			printf("rte_eth_dev_start:err=%d, port=%u\n",
1511 					retval, (unsigned) portid);
1512 			return -1;
1513 		}
1514 
1515 		rte_eth_promiscuous_enable(portid);
1516 
1517 		rte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]);
1518 
1519 		printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
1520 				(unsigned) portid,
1521 				l2fwd_ports_eth_addr[portid].addr_bytes[0],
1522 				l2fwd_ports_eth_addr[portid].addr_bytes[1],
1523 				l2fwd_ports_eth_addr[portid].addr_bytes[2],
1524 				l2fwd_ports_eth_addr[portid].addr_bytes[3],
1525 				l2fwd_ports_eth_addr[portid].addr_bytes[4],
1526 				l2fwd_ports_eth_addr[portid].addr_bytes[5]);
1527 
1528 		/* initialize port stats */
1529 		memset(&port_statistics, 0, sizeof(port_statistics));
1530 
1531 		/* Setup port forwarding table */
1532 		if (enabled_portcount % 2) {
1533 			l2fwd_dst_ports[portid] = last_portid;
1534 			l2fwd_dst_ports[last_portid] = portid;
1535 		} else {
1536 			last_portid = portid;
1537 		}
1538 
1539 		l2fwd_enabled_port_mask |= (1 << portid);
1540 		enabled_portcount++;
1541 	}
1542 
1543 	if (enabled_portcount == 1) {
1544 		l2fwd_dst_ports[last_portid] = last_portid;
1545 	} else if (enabled_portcount % 2) {
1546 		printf("odd number of ports in portmask- bye\n");
1547 		return -1;
1548 	}
1549 
1550 	check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);
1551 
1552 	return enabled_portcount;
1553 }
1554 
1555 static void
1556 reserve_key_memory(struct l2fwd_crypto_options *options)
1557 {
1558 	options->cipher_xform.cipher.key.data = rte_malloc("crypto key",
1559 						MAX_KEY_SIZE, 0);
1560 	if (options->cipher_xform.cipher.key.data == NULL)
1561 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for cipher key");
1562 
1563 
1564 	options->auth_xform.auth.key.data = rte_malloc("auth key",
1565 						MAX_KEY_SIZE, 0);
1566 	if (options->auth_xform.auth.key.data == NULL)
1567 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for auth key");
1568 
1569 	options->iv.data = rte_malloc("iv", MAX_KEY_SIZE, 0);
1570 	if (options->iv.data == NULL)
1571 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for IV");
1572 	options->iv.phys_addr = rte_malloc_virt2phy(options->iv.data);
1573 
1574 	options->aad.data = rte_malloc("aad", MAX_KEY_SIZE, 0);
1575 	if (options->aad.data == NULL)
1576 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for AAD");
1577 	options->aad.phys_addr = rte_malloc_virt2phy(options->aad.data);
1578 }
1579 
1580 int
1581 main(int argc, char **argv)
1582 {
1583 	struct lcore_queue_conf *qconf;
1584 	struct l2fwd_crypto_options options;
1585 
1586 	uint8_t nb_ports, nb_cryptodevs, portid, cdev_id;
1587 	unsigned lcore_id, rx_lcore_id;
1588 	int ret, enabled_cdevcount, enabled_portcount;
1589 	uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = {0};
1590 
1591 	/* init EAL */
1592 	ret = rte_eal_init(argc, argv);
1593 	if (ret < 0)
1594 		rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
1595 	argc -= ret;
1596 	argv += ret;
1597 
1598 	/* reserve memory for Cipher/Auth key and IV */
1599 	reserve_key_memory(&options);
1600 
1601 	/* parse application arguments (after the EAL ones) */
1602 	ret = l2fwd_crypto_parse_args(&options, argc, argv);
1603 	if (ret < 0)
1604 		rte_exit(EXIT_FAILURE, "Invalid L2FWD-CRYPTO arguments\n");
1605 
1606 	/* create the mbuf pool */
1607 	l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 512,
1608 			sizeof(struct rte_crypto_op),
1609 			RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
1610 	if (l2fwd_pktmbuf_pool == NULL)
1611 		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
1612 
1613 	/* create crypto op pool */
1614 	l2fwd_crypto_op_pool = rte_crypto_op_pool_create("crypto_op_pool",
1615 			RTE_CRYPTO_OP_TYPE_SYMMETRIC, NB_MBUF, 128, 0,
1616 			rte_socket_id());
1617 	if (l2fwd_crypto_op_pool == NULL)
1618 		rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n");
1619 
1620 	/* Enable Ethernet ports */
1621 	enabled_portcount = initialize_ports(&options);
1622 	if (enabled_portcount < 1)
1623 		rte_exit(EXIT_FAILURE, "Failed to initial Ethernet ports\n");
1624 
1625 	nb_ports = rte_eth_dev_count();
1626 	/* Initialize the port/queue configuration of each logical core */
1627 	for (rx_lcore_id = 0, qconf = NULL, portid = 0;
1628 			portid < nb_ports; portid++) {
1629 
1630 		/* skip ports that are not enabled */
1631 		if ((options.portmask & (1 << portid)) == 0)
1632 			continue;
1633 
1634 		if (options.single_lcore && qconf == NULL) {
1635 			while (rte_lcore_is_enabled(rx_lcore_id) == 0) {
1636 				rx_lcore_id++;
1637 				if (rx_lcore_id >= RTE_MAX_LCORE)
1638 					rte_exit(EXIT_FAILURE,
1639 							"Not enough cores\n");
1640 			}
1641 		} else if (!options.single_lcore) {
1642 			/* get the lcore_id for this port */
1643 			while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
1644 			       lcore_queue_conf[rx_lcore_id].nb_rx_ports ==
1645 			       options.nb_ports_per_lcore) {
1646 				rx_lcore_id++;
1647 				if (rx_lcore_id >= RTE_MAX_LCORE)
1648 					rte_exit(EXIT_FAILURE,
1649 							"Not enough cores\n");
1650 			}
1651 		}
1652 
1653 		/* Assigned a new logical core in the loop above. */
1654 		if (qconf != &lcore_queue_conf[rx_lcore_id])
1655 			qconf = &lcore_queue_conf[rx_lcore_id];
1656 
1657 		qconf->rx_port_list[qconf->nb_rx_ports] = portid;
1658 		qconf->nb_rx_ports++;
1659 
1660 		printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned)portid);
1661 	}
1662 
1663 	/* Enable Crypto devices */
1664 	enabled_cdevcount = initialize_cryptodevs(&options, enabled_portcount,
1665 			enabled_cdevs);
1666 	if (enabled_cdevcount < 0)
1667 		rte_exit(EXIT_FAILURE, "Failed to initialize crypto devices\n");
1668 
1669 	if (enabled_cdevcount < enabled_portcount)
1670 		rte_exit(EXIT_FAILURE, "Number of capable crypto devices (%d) "
1671 				"has to be more or equal to number of ports (%d)\n",
1672 				enabled_cdevcount, enabled_portcount);
1673 
1674 	nb_cryptodevs = rte_cryptodev_count();
1675 
1676 	/* Initialize the port/cryptodev configuration of each logical core */
1677 	for (rx_lcore_id = 0, qconf = NULL, cdev_id = 0;
1678 			cdev_id < nb_cryptodevs && enabled_cdevcount;
1679 			cdev_id++) {
1680 		/* Crypto op not supported by crypto device */
1681 		if (!enabled_cdevs[cdev_id])
1682 			continue;
1683 
1684 		if (options.single_lcore && qconf == NULL) {
1685 			while (rte_lcore_is_enabled(rx_lcore_id) == 0) {
1686 				rx_lcore_id++;
1687 				if (rx_lcore_id >= RTE_MAX_LCORE)
1688 					rte_exit(EXIT_FAILURE,
1689 							"Not enough cores\n");
1690 			}
1691 		} else if (!options.single_lcore) {
1692 			/* get the lcore_id for this port */
1693 			while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
1694 			       lcore_queue_conf[rx_lcore_id].nb_crypto_devs ==
1695 			       options.nb_ports_per_lcore) {
1696 				rx_lcore_id++;
1697 				if (rx_lcore_id >= RTE_MAX_LCORE)
1698 					rte_exit(EXIT_FAILURE,
1699 							"Not enough cores\n");
1700 			}
1701 		}
1702 
1703 		/* Assigned a new logical core in the loop above. */
1704 		if (qconf != &lcore_queue_conf[rx_lcore_id])
1705 			qconf = &lcore_queue_conf[rx_lcore_id];
1706 
1707 		qconf->cryptodev_list[qconf->nb_crypto_devs] = cdev_id;
1708 		qconf->nb_crypto_devs++;
1709 
1710 		enabled_cdevcount--;
1711 
1712 		printf("Lcore %u: cryptodev %u\n", rx_lcore_id,
1713 				(unsigned)cdev_id);
1714 	}
1715 
1716 	/* launch per-lcore init on every lcore */
1717 	rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, (void *)&options,
1718 			CALL_MASTER);
1719 	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1720 		if (rte_eal_wait_lcore(lcore_id) < 0)
1721 			return -1;
1722 	}
1723 
1724 	return 0;
1725 }
1726