xref: /dpdk/examples/l2fwd-crypto/main.c (revision ceb1ccd5d50c1a89ba8bdd97cc199e7f07422b98)
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("NULL", optarg) == 0) {
863 		*algo = RTE_CRYPTO_CIPHER_NULL;
864 		return 0;
865 	} else if (strcmp("SNOW3G_UEA2", optarg) == 0) {
866 		*algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2;
867 		return 0;
868 	}
869 
870 	printf("Cipher algorithm  not supported!\n");
871 	return -1;
872 }
873 
874 /** Parse crypto cipher operation command line argument */
875 static int
876 parse_cipher_op(enum rte_crypto_cipher_operation *op, char *optarg)
877 {
878 	if (strcmp("ENCRYPT", optarg) == 0) {
879 		*op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
880 		return 0;
881 	} else if (strcmp("DECRYPT", optarg) == 0) {
882 		*op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
883 		return 0;
884 	}
885 
886 	printf("Cipher operation not supported!\n");
887 	return -1;
888 }
889 
890 /** Parse crypto key command line argument */
891 static int
892 parse_key(uint8_t *data, char *input_arg)
893 {
894 	unsigned byte_count;
895 	char *token;
896 
897 	for (byte_count = 0, token = strtok(input_arg, ":");
898 			(byte_count < MAX_KEY_SIZE) && (token != NULL);
899 			token = strtok(NULL, ":")) {
900 
901 		int number = (int)strtol(token, NULL, 16);
902 
903 		if (errno == EINVAL || errno == ERANGE || number > 0xFF)
904 			return -1;
905 
906 		data[byte_count++] = (uint8_t)number;
907 	}
908 
909 	return 0;
910 }
911 
912 /** Parse crypto cipher operation command line argument */
913 static int
914 parse_auth_algo(enum rte_crypto_auth_algorithm *algo, char *optarg)
915 {
916 	if (strcmp("AES_GCM", optarg) == 0) {
917 		*algo = RTE_CRYPTO_AUTH_AES_GCM;
918 		return 0;
919 	} else if (strcmp("MD5_HMAC", optarg) == 0) {
920 		*algo = RTE_CRYPTO_AUTH_MD5_HMAC;
921 		return 0;
922 	} else if (strcmp("NULL", optarg) == 0) {
923 		*algo = RTE_CRYPTO_AUTH_NULL;
924 		return 0;
925 	} else if (strcmp("SHA1_HMAC", optarg) == 0) {
926 		*algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
927 		return 0;
928 	} else if (strcmp("SHA224_HMAC", optarg) == 0) {
929 		*algo = RTE_CRYPTO_AUTH_SHA224_HMAC;
930 		return 0;
931 	} else if (strcmp("SHA256_HMAC", optarg) == 0) {
932 		*algo = RTE_CRYPTO_AUTH_SHA256_HMAC;
933 		return 0;
934 	}  else if (strcmp("SHA384_HMAC", optarg) == 0) {
935 		*algo = RTE_CRYPTO_AUTH_SHA384_HMAC;
936 		return 0;
937 	} else if (strcmp("SHA512_HMAC", optarg) == 0) {
938 		*algo = RTE_CRYPTO_AUTH_SHA512_HMAC;
939 		return 0;
940 	} else if (strcmp("SNOW3G_UIA2", optarg) == 0) {
941 		*algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2;
942 		return 0;
943 	}
944 
945 	printf("Authentication algorithm specified not supported!\n");
946 	return -1;
947 }
948 
949 static int
950 parse_auth_op(enum rte_crypto_auth_operation *op, char *optarg)
951 {
952 	if (strcmp("VERIFY", optarg) == 0) {
953 		*op = RTE_CRYPTO_AUTH_OP_VERIFY;
954 		return 0;
955 	} else if (strcmp("GENERATE", optarg) == 0) {
956 		*op = RTE_CRYPTO_AUTH_OP_GENERATE;
957 		return 0;
958 	}
959 
960 	printf("Authentication operation specified not supported!\n");
961 	return -1;
962 }
963 
964 /** Parse long options */
965 static int
966 l2fwd_crypto_parse_args_long_options(struct l2fwd_crypto_options *options,
967 		struct option *lgopts, int option_index)
968 {
969 	int retval;
970 
971 	if (strcmp(lgopts[option_index].name, "cdev_type") == 0)
972 		return parse_cryptodev_type(&options->type, optarg);
973 
974 	else if (strcmp(lgopts[option_index].name, "chain") == 0)
975 		return parse_crypto_opt_chain(options, optarg);
976 
977 	/* Cipher options */
978 	else if (strcmp(lgopts[option_index].name, "cipher_algo") == 0) {
979 		retval = parse_cipher_algo(&options->cipher_xform.cipher.algo,
980 				optarg);
981 		if (retval == 0)
982 			strcpy(options->string_cipher_algo, optarg);
983 		return retval;
984 	}
985 
986 	else if (strcmp(lgopts[option_index].name, "cipher_op") == 0)
987 		return parse_cipher_op(&options->cipher_xform.cipher.op,
988 				optarg);
989 
990 	else if (strcmp(lgopts[option_index].name, "cipher_key") == 0) {
991 		options->ckey_param = 1;
992 		return parse_key(options->cipher_xform.cipher.key.data, optarg);
993 	}
994 
995 	else if (strcmp(lgopts[option_index].name, "iv") == 0) {
996 		options->iv_param = 1;
997 		return parse_key(options->iv.data, optarg);
998 	}
999 
1000 	/* Authentication options */
1001 	else if (strcmp(lgopts[option_index].name, "auth_algo") == 0) {
1002 		retval = parse_auth_algo(&options->auth_xform.auth.algo,
1003 				optarg);
1004 		if (retval == 0)
1005 			strcpy(options->string_auth_algo, optarg);
1006 		return retval;
1007 	}
1008 
1009 	else if (strcmp(lgopts[option_index].name, "auth_op") == 0)
1010 		return parse_auth_op(&options->auth_xform.auth.op,
1011 				optarg);
1012 
1013 	else if (strcmp(lgopts[option_index].name, "auth_key") == 0) {
1014 		options->akey_param = 1;
1015 		return parse_key(options->auth_xform.auth.key.data, optarg);
1016 	}
1017 
1018 	else if (strcmp(lgopts[option_index].name, "aad") == 0) {
1019 		options->aad_param = 1;
1020 		return parse_key(options->aad.data, optarg);
1021 	}
1022 
1023 	else if (strcmp(lgopts[option_index].name, "sessionless") == 0) {
1024 		options->sessionless = 1;
1025 		return 0;
1026 	}
1027 
1028 	return -1;
1029 }
1030 
1031 /** Parse port mask */
1032 static int
1033 l2fwd_crypto_parse_portmask(struct l2fwd_crypto_options *options,
1034 		const char *q_arg)
1035 {
1036 	char *end = NULL;
1037 	unsigned long pm;
1038 
1039 	/* parse hexadecimal string */
1040 	pm = strtoul(q_arg, &end, 16);
1041 	if ((pm == '\0') || (end == NULL) || (*end != '\0'))
1042 		pm = 0;
1043 
1044 	options->portmask = pm;
1045 	if (options->portmask == 0) {
1046 		printf("invalid portmask specified\n");
1047 		return -1;
1048 	}
1049 
1050 	return pm;
1051 }
1052 
1053 /** Parse number of queues */
1054 static int
1055 l2fwd_crypto_parse_nqueue(struct l2fwd_crypto_options *options,
1056 		const char *q_arg)
1057 {
1058 	char *end = NULL;
1059 	unsigned long n;
1060 
1061 	/* parse hexadecimal string */
1062 	n = strtoul(q_arg, &end, 10);
1063 	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1064 		n = 0;
1065 	else if (n >= MAX_RX_QUEUE_PER_LCORE)
1066 		n = 0;
1067 
1068 	options->nb_ports_per_lcore = n;
1069 	if (options->nb_ports_per_lcore == 0) {
1070 		printf("invalid number of ports selected\n");
1071 		return -1;
1072 	}
1073 
1074 	return 0;
1075 }
1076 
1077 /** Parse timer period */
1078 static int
1079 l2fwd_crypto_parse_timer_period(struct l2fwd_crypto_options *options,
1080 		const char *q_arg)
1081 {
1082 	char *end = NULL;
1083 	unsigned long n;
1084 
1085 	/* parse number string */
1086 	n = (unsigned)strtol(q_arg, &end, 10);
1087 	if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
1088 		n = 0;
1089 
1090 	if (n >= MAX_TIMER_PERIOD) {
1091 		printf("Warning refresh period specified %lu is greater than "
1092 				"max value %lu! using max value",
1093 				n, MAX_TIMER_PERIOD);
1094 		n = MAX_TIMER_PERIOD;
1095 	}
1096 
1097 	options->refresh_period = n * 1000 * TIMER_MILLISECOND;
1098 
1099 	return 0;
1100 }
1101 
1102 /** Generate default options for application */
1103 static void
1104 l2fwd_crypto_default_options(struct l2fwd_crypto_options *options)
1105 {
1106 	srand(time(NULL));
1107 
1108 	options->portmask = 0xffffffff;
1109 	options->nb_ports_per_lcore = 1;
1110 	options->refresh_period = 10000;
1111 	options->single_lcore = 0;
1112 	options->sessionless = 0;
1113 
1114 	options->xform_chain = L2FWD_CRYPTO_CIPHER_HASH;
1115 
1116 	/* Cipher Data */
1117 	options->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
1118 	options->cipher_xform.next = NULL;
1119 	options->ckey_param = 0;
1120 	options->iv_param = 0;
1121 
1122 	options->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
1123 	options->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
1124 
1125 	/* Authentication Data */
1126 	options->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
1127 	options->auth_xform.next = NULL;
1128 	options->akey_param = 0;
1129 	options->aad_param = 0;
1130 
1131 	options->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
1132 	options->auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE;
1133 
1134 	options->type = CDEV_TYPE_ANY;
1135 }
1136 
1137 static void
1138 l2fwd_crypto_options_print(struct l2fwd_crypto_options *options)
1139 {
1140 	printf("Options:-\nn");
1141 	printf("portmask: %x\n", options->portmask);
1142 	printf("ports per lcore: %u\n", options->nb_ports_per_lcore);
1143 	printf("refresh period : %u\n", options->refresh_period);
1144 	printf("single lcore mode: %s\n",
1145 			options->single_lcore ? "enabled" : "disabled");
1146 	printf("stats_printing: %s\n",
1147 			options->refresh_period == 0 ? "disabled" : "enabled");
1148 
1149 	printf("sessionless crypto: %s\n",
1150 			options->sessionless ? "enabled" : "disabled");
1151 }
1152 
1153 /* Parse the argument given in the command line of the application */
1154 static int
1155 l2fwd_crypto_parse_args(struct l2fwd_crypto_options *options,
1156 		int argc, char **argv)
1157 {
1158 	int opt, retval, option_index;
1159 	char **argvopt = argv, *prgname = argv[0];
1160 
1161 	static struct option lgopts[] = {
1162 			{ "sessionless", no_argument, 0, 0 },
1163 
1164 			{ "cdev_type", required_argument, 0, 0 },
1165 			{ "chain", required_argument, 0, 0 },
1166 
1167 			{ "cipher_algo", required_argument, 0, 0 },
1168 			{ "cipher_op", required_argument, 0, 0 },
1169 			{ "cipher_key", required_argument, 0, 0 },
1170 
1171 			{ "auth_algo", required_argument, 0, 0 },
1172 			{ "auth_op", required_argument, 0, 0 },
1173 			{ "auth_key", required_argument, 0, 0 },
1174 
1175 			{ "iv", required_argument, 0, 0 },
1176 			{ "aad", required_argument, 0, 0 },
1177 
1178 			{ "sessionless", no_argument, 0, 0 },
1179 
1180 			{ NULL, 0, 0, 0 }
1181 	};
1182 
1183 	l2fwd_crypto_default_options(options);
1184 
1185 	while ((opt = getopt_long(argc, argvopt, "p:q:st:", lgopts,
1186 			&option_index)) != EOF) {
1187 		switch (opt) {
1188 		/* long options */
1189 		case 0:
1190 			retval = l2fwd_crypto_parse_args_long_options(options,
1191 					lgopts, option_index);
1192 			if (retval < 0) {
1193 				l2fwd_crypto_usage(prgname);
1194 				return -1;
1195 			}
1196 			break;
1197 
1198 		/* portmask */
1199 		case 'p':
1200 			retval = l2fwd_crypto_parse_portmask(options, optarg);
1201 			if (retval < 0) {
1202 				l2fwd_crypto_usage(prgname);
1203 				return -1;
1204 			}
1205 			break;
1206 
1207 		/* nqueue */
1208 		case 'q':
1209 			retval = l2fwd_crypto_parse_nqueue(options, optarg);
1210 			if (retval < 0) {
1211 				l2fwd_crypto_usage(prgname);
1212 				return -1;
1213 			}
1214 			break;
1215 
1216 		/* single  */
1217 		case 's':
1218 			options->single_lcore = 1;
1219 
1220 			break;
1221 
1222 		/* timer period */
1223 		case 't':
1224 			retval = l2fwd_crypto_parse_timer_period(options,
1225 					optarg);
1226 			if (retval < 0) {
1227 				l2fwd_crypto_usage(prgname);
1228 				return -1;
1229 			}
1230 			break;
1231 
1232 		default:
1233 			l2fwd_crypto_usage(prgname);
1234 			return -1;
1235 		}
1236 	}
1237 
1238 
1239 	if (optind >= 0)
1240 		argv[optind-1] = prgname;
1241 
1242 	retval = optind-1;
1243 	optind = 0; /* reset getopt lib */
1244 
1245 	return retval;
1246 }
1247 
1248 /* Check the link status of all ports in up to 9s, and print them finally */
1249 static void
1250 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
1251 {
1252 #define CHECK_INTERVAL 100 /* 100ms */
1253 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
1254 	uint8_t portid, count, all_ports_up, print_flag = 0;
1255 	struct rte_eth_link link;
1256 
1257 	printf("\nChecking link status");
1258 	fflush(stdout);
1259 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
1260 		all_ports_up = 1;
1261 		for (portid = 0; portid < port_num; portid++) {
1262 			if ((port_mask & (1 << portid)) == 0)
1263 				continue;
1264 			memset(&link, 0, sizeof(link));
1265 			rte_eth_link_get_nowait(portid, &link);
1266 			/* print link status if flag set */
1267 			if (print_flag == 1) {
1268 				if (link.link_status)
1269 					printf("Port %d Link Up - speed %u "
1270 						"Mbps - %s\n", (uint8_t)portid,
1271 						(unsigned)link.link_speed,
1272 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
1273 					("full-duplex") : ("half-duplex\n"));
1274 				else
1275 					printf("Port %d Link Down\n",
1276 						(uint8_t)portid);
1277 				continue;
1278 			}
1279 			/* clear all_ports_up flag if any link down */
1280 			if (link.link_status == 0) {
1281 				all_ports_up = 0;
1282 				break;
1283 			}
1284 		}
1285 		/* after finally printing all link status, get out */
1286 		if (print_flag == 1)
1287 			break;
1288 
1289 		if (all_ports_up == 0) {
1290 			printf(".");
1291 			fflush(stdout);
1292 			rte_delay_ms(CHECK_INTERVAL);
1293 		}
1294 
1295 		/* set the print_flag if all ports up or timeout */
1296 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
1297 			print_flag = 1;
1298 			printf("done\n");
1299 		}
1300 	}
1301 }
1302 
1303 /* Check if device has to be HW/SW or any */
1304 static int
1305 check_type(struct l2fwd_crypto_options *options, struct rte_cryptodev_info *dev_info)
1306 {
1307 	if (options->type == CDEV_TYPE_HW &&
1308 			(dev_info->feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED))
1309 		return 0;
1310 	if (options->type == CDEV_TYPE_SW &&
1311 			!(dev_info->feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED))
1312 		return 0;
1313 	if (options->type == CDEV_TYPE_ANY)
1314 		return 0;
1315 
1316 	return -1;
1317 }
1318 
1319 static int
1320 initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports,
1321 		uint8_t *enabled_cdevs)
1322 {
1323 	unsigned i, cdev_id, cdev_count, enabled_cdev_count = 0;
1324 	const struct rte_cryptodev_capabilities *cap;
1325 	enum rte_crypto_auth_algorithm cap_auth_algo;
1326 	enum rte_crypto_auth_algorithm opt_auth_algo;
1327 	enum rte_crypto_cipher_algorithm cap_cipher_algo;
1328 	enum rte_crypto_cipher_algorithm opt_cipher_algo;
1329 	int retval;
1330 
1331 	cdev_count = rte_cryptodev_count();
1332 	if (cdev_count == 0) {
1333 		printf("No crypto devices available\n");
1334 		return -1;
1335 	}
1336 
1337 	for (cdev_id = 0; cdev_id < cdev_count && enabled_cdev_count < nb_ports;
1338 			cdev_id++) {
1339 		struct rte_cryptodev_qp_conf qp_conf;
1340 		struct rte_cryptodev_info dev_info;
1341 
1342 		struct rte_cryptodev_config conf = {
1343 			.nb_queue_pairs = 1,
1344 			.socket_id = SOCKET_ID_ANY,
1345 			.session_mp = {
1346 				.nb_objs = 2048,
1347 				.cache_size = 64
1348 			}
1349 		};
1350 
1351 		rte_cryptodev_info_get(cdev_id, &dev_info);
1352 
1353 		/* Set cipher parameters */
1354 		if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
1355 				options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
1356 				options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
1357 			/* Check if device supports cipher algo */
1358 			i = 0;
1359 			opt_cipher_algo = options->cipher_xform.cipher.algo;
1360 			cap = &dev_info.capabilities[i];
1361 			while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1362 				cap_cipher_algo = cap->sym.cipher.algo;
1363 				if (cap->sym.xform_type ==
1364 						RTE_CRYPTO_SYM_XFORM_CIPHER) {
1365 					if (cap_cipher_algo == opt_cipher_algo) {
1366 						if (check_type(options, &dev_info) == 0)
1367 							break;
1368 					}
1369 				}
1370 				cap = &dev_info.capabilities[++i];
1371 			}
1372 
1373 			if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1374 				printf("Algorithm %s not supported by cryptodev %u"
1375 					" or device not of preferred type (%s)\n",
1376 					options->string_cipher_algo, cdev_id,
1377 					options->string_type);
1378 				continue;
1379 			}
1380 
1381 			options->block_size = cap->sym.cipher.block_size;
1382 			options->iv.length = cap->sym.cipher.iv_size.min;
1383 			options->cipher_xform.cipher.key.length =
1384 						cap->sym.cipher.key_size.min;
1385 			if (!options->ckey_param)
1386 				generate_random_key(
1387 					options->cipher_xform.cipher.key.data,
1388 					options->cipher_xform.cipher.key.length);
1389 
1390 		}
1391 
1392 		/* Set auth parameters */
1393 		if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
1394 				options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
1395 				options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) {
1396 			/* Check if device supports auth algo */
1397 			i = 0;
1398 			opt_auth_algo = options->auth_xform.auth.algo;
1399 			cap = &dev_info.capabilities[i];
1400 			while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1401 				cap_auth_algo = cap->sym.auth.algo;
1402 				if ((cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AUTH) &&
1403 						(cap_auth_algo == opt_auth_algo) &&
1404 						(check_type(options, &dev_info) == 0)) {
1405 					break;
1406 				}
1407 				cap = &dev_info.capabilities[++i];
1408 			}
1409 
1410 			if (cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
1411 				printf("Algorithm %s not supported by cryptodev %u"
1412 					" or device not of preferred type (%s)\n",
1413 					options->string_auth_algo, cdev_id,
1414 					options->string_type);
1415 				continue;
1416 			}
1417 
1418 			options->block_size = cap->sym.auth.block_size;
1419 			options->auth_xform.auth.add_auth_data_length =
1420 						cap->sym.auth.aad_size.min;
1421 			options->auth_xform.auth.digest_length =
1422 						cap->sym.auth.digest_size.min;
1423 			options->auth_xform.auth.key.length =
1424 						cap->sym.auth.key_size.min;
1425 
1426 			if (!options->akey_param)
1427 				generate_random_key(
1428 					options->auth_xform.auth.key.data,
1429 					options->auth_xform.auth.key.length);
1430 		}
1431 
1432 		retval = rte_cryptodev_configure(cdev_id, &conf);
1433 		if (retval < 0) {
1434 			printf("Failed to configure cryptodev %u", cdev_id);
1435 			return -1;
1436 		}
1437 
1438 		qp_conf.nb_descriptors = 2048;
1439 
1440 		retval = rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
1441 				SOCKET_ID_ANY);
1442 		if (retval < 0) {
1443 			printf("Failed to setup queue pair %u on cryptodev %u",
1444 					0, cdev_id);
1445 			return -1;
1446 		}
1447 
1448 		l2fwd_enabled_crypto_mask |= (1 << cdev_id);
1449 
1450 		enabled_cdevs[cdev_id] = 1;
1451 		enabled_cdev_count++;
1452 	}
1453 
1454 	return enabled_cdev_count;
1455 }
1456 
1457 static int
1458 initialize_ports(struct l2fwd_crypto_options *options)
1459 {
1460 	uint8_t last_portid, portid;
1461 	unsigned enabled_portcount = 0;
1462 	unsigned nb_ports = rte_eth_dev_count();
1463 
1464 	if (nb_ports == 0) {
1465 		printf("No Ethernet ports - bye\n");
1466 		return -1;
1467 	}
1468 
1469 	if (nb_ports > RTE_MAX_ETHPORTS)
1470 		nb_ports = RTE_MAX_ETHPORTS;
1471 
1472 	/* Reset l2fwd_dst_ports */
1473 	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
1474 		l2fwd_dst_ports[portid] = 0;
1475 
1476 	for (last_portid = 0, portid = 0; portid < nb_ports; portid++) {
1477 		int retval;
1478 
1479 		/* Skip ports that are not enabled */
1480 		if ((options->portmask & (1 << portid)) == 0)
1481 			continue;
1482 
1483 		/* init port */
1484 		printf("Initializing port %u... ", (unsigned) portid);
1485 		fflush(stdout);
1486 		retval = rte_eth_dev_configure(portid, 1, 1, &port_conf);
1487 		if (retval < 0) {
1488 			printf("Cannot configure device: err=%d, port=%u\n",
1489 				  retval, (unsigned) portid);
1490 			return -1;
1491 		}
1492 
1493 		/* init one RX queue */
1494 		fflush(stdout);
1495 		retval = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
1496 					     rte_eth_dev_socket_id(portid),
1497 					     NULL, l2fwd_pktmbuf_pool);
1498 		if (retval < 0) {
1499 			printf("rte_eth_rx_queue_setup:err=%d, port=%u\n",
1500 					retval, (unsigned) portid);
1501 			return -1;
1502 		}
1503 
1504 		/* init one TX queue on each port */
1505 		fflush(stdout);
1506 		retval = rte_eth_tx_queue_setup(portid, 0, nb_txd,
1507 				rte_eth_dev_socket_id(portid),
1508 				NULL);
1509 		if (retval < 0) {
1510 			printf("rte_eth_tx_queue_setup:err=%d, port=%u\n",
1511 				retval, (unsigned) portid);
1512 
1513 			return -1;
1514 		}
1515 
1516 		/* Start device */
1517 		retval = rte_eth_dev_start(portid);
1518 		if (retval < 0) {
1519 			printf("rte_eth_dev_start:err=%d, port=%u\n",
1520 					retval, (unsigned) portid);
1521 			return -1;
1522 		}
1523 
1524 		rte_eth_promiscuous_enable(portid);
1525 
1526 		rte_eth_macaddr_get(portid, &l2fwd_ports_eth_addr[portid]);
1527 
1528 		printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
1529 				(unsigned) portid,
1530 				l2fwd_ports_eth_addr[portid].addr_bytes[0],
1531 				l2fwd_ports_eth_addr[portid].addr_bytes[1],
1532 				l2fwd_ports_eth_addr[portid].addr_bytes[2],
1533 				l2fwd_ports_eth_addr[portid].addr_bytes[3],
1534 				l2fwd_ports_eth_addr[portid].addr_bytes[4],
1535 				l2fwd_ports_eth_addr[portid].addr_bytes[5]);
1536 
1537 		/* initialize port stats */
1538 		memset(&port_statistics, 0, sizeof(port_statistics));
1539 
1540 		/* Setup port forwarding table */
1541 		if (enabled_portcount % 2) {
1542 			l2fwd_dst_ports[portid] = last_portid;
1543 			l2fwd_dst_ports[last_portid] = portid;
1544 		} else {
1545 			last_portid = portid;
1546 		}
1547 
1548 		l2fwd_enabled_port_mask |= (1 << portid);
1549 		enabled_portcount++;
1550 	}
1551 
1552 	if (enabled_portcount == 1) {
1553 		l2fwd_dst_ports[last_portid] = last_portid;
1554 	} else if (enabled_portcount % 2) {
1555 		printf("odd number of ports in portmask- bye\n");
1556 		return -1;
1557 	}
1558 
1559 	check_all_ports_link_status(nb_ports, l2fwd_enabled_port_mask);
1560 
1561 	return enabled_portcount;
1562 }
1563 
1564 static void
1565 reserve_key_memory(struct l2fwd_crypto_options *options)
1566 {
1567 	options->cipher_xform.cipher.key.data = rte_malloc("crypto key",
1568 						MAX_KEY_SIZE, 0);
1569 	if (options->cipher_xform.cipher.key.data == NULL)
1570 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for cipher key");
1571 
1572 
1573 	options->auth_xform.auth.key.data = rte_malloc("auth key",
1574 						MAX_KEY_SIZE, 0);
1575 	if (options->auth_xform.auth.key.data == NULL)
1576 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for auth key");
1577 
1578 	options->iv.data = rte_malloc("iv", MAX_KEY_SIZE, 0);
1579 	if (options->iv.data == NULL)
1580 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for IV");
1581 	options->iv.phys_addr = rte_malloc_virt2phy(options->iv.data);
1582 
1583 	options->aad.data = rte_malloc("aad", MAX_KEY_SIZE, 0);
1584 	if (options->aad.data == NULL)
1585 		rte_exit(EXIT_FAILURE, "Failed to allocate memory for AAD");
1586 	options->aad.phys_addr = rte_malloc_virt2phy(options->aad.data);
1587 }
1588 
1589 int
1590 main(int argc, char **argv)
1591 {
1592 	struct lcore_queue_conf *qconf;
1593 	struct l2fwd_crypto_options options;
1594 
1595 	uint8_t nb_ports, nb_cryptodevs, portid, cdev_id;
1596 	unsigned lcore_id, rx_lcore_id;
1597 	int ret, enabled_cdevcount, enabled_portcount;
1598 	uint8_t enabled_cdevs[RTE_CRYPTO_MAX_DEVS] = {0};
1599 
1600 	/* init EAL */
1601 	ret = rte_eal_init(argc, argv);
1602 	if (ret < 0)
1603 		rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
1604 	argc -= ret;
1605 	argv += ret;
1606 
1607 	/* reserve memory for Cipher/Auth key and IV */
1608 	reserve_key_memory(&options);
1609 
1610 	/* parse application arguments (after the EAL ones) */
1611 	ret = l2fwd_crypto_parse_args(&options, argc, argv);
1612 	if (ret < 0)
1613 		rte_exit(EXIT_FAILURE, "Invalid L2FWD-CRYPTO arguments\n");
1614 
1615 	/* create the mbuf pool */
1616 	l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 512,
1617 			sizeof(struct rte_crypto_op),
1618 			RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
1619 	if (l2fwd_pktmbuf_pool == NULL)
1620 		rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
1621 
1622 	/* create crypto op pool */
1623 	l2fwd_crypto_op_pool = rte_crypto_op_pool_create("crypto_op_pool",
1624 			RTE_CRYPTO_OP_TYPE_SYMMETRIC, NB_MBUF, 128, 0,
1625 			rte_socket_id());
1626 	if (l2fwd_crypto_op_pool == NULL)
1627 		rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n");
1628 
1629 	/* Enable Ethernet ports */
1630 	enabled_portcount = initialize_ports(&options);
1631 	if (enabled_portcount < 1)
1632 		rte_exit(EXIT_FAILURE, "Failed to initial Ethernet ports\n");
1633 
1634 	nb_ports = rte_eth_dev_count();
1635 	/* Initialize the port/queue configuration of each logical core */
1636 	for (rx_lcore_id = 0, qconf = NULL, portid = 0;
1637 			portid < nb_ports; portid++) {
1638 
1639 		/* skip ports that are not enabled */
1640 		if ((options.portmask & (1 << portid)) == 0)
1641 			continue;
1642 
1643 		if (options.single_lcore && qconf == NULL) {
1644 			while (rte_lcore_is_enabled(rx_lcore_id) == 0) {
1645 				rx_lcore_id++;
1646 				if (rx_lcore_id >= RTE_MAX_LCORE)
1647 					rte_exit(EXIT_FAILURE,
1648 							"Not enough cores\n");
1649 			}
1650 		} else if (!options.single_lcore) {
1651 			/* get the lcore_id for this port */
1652 			while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
1653 			       lcore_queue_conf[rx_lcore_id].nb_rx_ports ==
1654 			       options.nb_ports_per_lcore) {
1655 				rx_lcore_id++;
1656 				if (rx_lcore_id >= RTE_MAX_LCORE)
1657 					rte_exit(EXIT_FAILURE,
1658 							"Not enough cores\n");
1659 			}
1660 		}
1661 
1662 		/* Assigned a new logical core in the loop above. */
1663 		if (qconf != &lcore_queue_conf[rx_lcore_id])
1664 			qconf = &lcore_queue_conf[rx_lcore_id];
1665 
1666 		qconf->rx_port_list[qconf->nb_rx_ports] = portid;
1667 		qconf->nb_rx_ports++;
1668 
1669 		printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned)portid);
1670 	}
1671 
1672 	/* Enable Crypto devices */
1673 	enabled_cdevcount = initialize_cryptodevs(&options, enabled_portcount,
1674 			enabled_cdevs);
1675 	if (enabled_cdevcount < 0)
1676 		rte_exit(EXIT_FAILURE, "Failed to initialize crypto devices\n");
1677 
1678 	if (enabled_cdevcount < enabled_portcount)
1679 		rte_exit(EXIT_FAILURE, "Number of capable crypto devices (%d) "
1680 				"has to be more or equal to number of ports (%d)\n",
1681 				enabled_cdevcount, enabled_portcount);
1682 
1683 	nb_cryptodevs = rte_cryptodev_count();
1684 
1685 	/* Initialize the port/cryptodev configuration of each logical core */
1686 	for (rx_lcore_id = 0, qconf = NULL, cdev_id = 0;
1687 			cdev_id < nb_cryptodevs && enabled_cdevcount;
1688 			cdev_id++) {
1689 		/* Crypto op not supported by crypto device */
1690 		if (!enabled_cdevs[cdev_id])
1691 			continue;
1692 
1693 		if (options.single_lcore && qconf == NULL) {
1694 			while (rte_lcore_is_enabled(rx_lcore_id) == 0) {
1695 				rx_lcore_id++;
1696 				if (rx_lcore_id >= RTE_MAX_LCORE)
1697 					rte_exit(EXIT_FAILURE,
1698 							"Not enough cores\n");
1699 			}
1700 		} else if (!options.single_lcore) {
1701 			/* get the lcore_id for this port */
1702 			while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
1703 			       lcore_queue_conf[rx_lcore_id].nb_crypto_devs ==
1704 			       options.nb_ports_per_lcore) {
1705 				rx_lcore_id++;
1706 				if (rx_lcore_id >= RTE_MAX_LCORE)
1707 					rte_exit(EXIT_FAILURE,
1708 							"Not enough cores\n");
1709 			}
1710 		}
1711 
1712 		/* Assigned a new logical core in the loop above. */
1713 		if (qconf != &lcore_queue_conf[rx_lcore_id])
1714 			qconf = &lcore_queue_conf[rx_lcore_id];
1715 
1716 		qconf->cryptodev_list[qconf->nb_crypto_devs] = cdev_id;
1717 		qconf->nb_crypto_devs++;
1718 
1719 		enabled_cdevcount--;
1720 
1721 		printf("Lcore %u: cryptodev %u\n", rx_lcore_id,
1722 				(unsigned)cdev_id);
1723 	}
1724 
1725 	/* launch per-lcore init on every lcore */
1726 	rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, (void *)&options,
1727 			CALL_MASTER);
1728 	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1729 		if (rte_eal_wait_lcore(lcore_id) < 0)
1730 			return -1;
1731 	}
1732 
1733 	return 0;
1734 }
1735