xref: /f-stack/dpdk/examples/bbdev_app/main.c (revision 2d9fd380)
1d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2d30ea906Sjfb8856606  * Copyright(c) 2017 Intel Corporation
3d30ea906Sjfb8856606  */
4d30ea906Sjfb8856606 
5d30ea906Sjfb8856606 #include <stdio.h>
6d30ea906Sjfb8856606 #include <stdlib.h>
7d30ea906Sjfb8856606 #include <string.h>
8d30ea906Sjfb8856606 #include <stdint.h>
9d30ea906Sjfb8856606 #include <inttypes.h>
10d30ea906Sjfb8856606 #include <sys/types.h>
11d30ea906Sjfb8856606 #include <sys/unistd.h>
12d30ea906Sjfb8856606 #include <sys/queue.h>
13d30ea906Sjfb8856606 #include <stdarg.h>
14d30ea906Sjfb8856606 #include <ctype.h>
15d30ea906Sjfb8856606 #include <errno.h>
16d30ea906Sjfb8856606 #include <math.h>
17d30ea906Sjfb8856606 #include <assert.h>
18d30ea906Sjfb8856606 #include <getopt.h>
19d30ea906Sjfb8856606 #include <signal.h>
20d30ea906Sjfb8856606 
21*2d9fd380Sjfb8856606 #include <rte_atomic.h>
22*2d9fd380Sjfb8856606 #include <rte_common.h>
23*2d9fd380Sjfb8856606 #include <rte_eal.h>
24*2d9fd380Sjfb8856606 #include <rte_cycles.h>
25*2d9fd380Sjfb8856606 #include <rte_ether.h>
26*2d9fd380Sjfb8856606 #include <rte_ethdev.h>
27*2d9fd380Sjfb8856606 #include <rte_ip.h>
28*2d9fd380Sjfb8856606 #include <rte_lcore.h>
29*2d9fd380Sjfb8856606 #include <rte_malloc.h>
30*2d9fd380Sjfb8856606 #include <rte_mbuf.h>
31*2d9fd380Sjfb8856606 #include <rte_mbuf_dyn.h>
32*2d9fd380Sjfb8856606 #include <rte_memory.h>
33*2d9fd380Sjfb8856606 #include <rte_mempool.h>
34*2d9fd380Sjfb8856606 #include <rte_log.h>
35*2d9fd380Sjfb8856606 #include <rte_bbdev.h>
36*2d9fd380Sjfb8856606 #include <rte_bbdev_op.h>
37d30ea906Sjfb8856606 
38d30ea906Sjfb8856606 /* LLR values - negative value for '1' bit */
39d30ea906Sjfb8856606 #define LLR_1_BIT 0x81
40d30ea906Sjfb8856606 #define LLR_0_BIT 0x7F
41d30ea906Sjfb8856606 
42d30ea906Sjfb8856606 #define MAX_PKT_BURST 32
43d30ea906Sjfb8856606 #define NB_MBUF 8191
44d30ea906Sjfb8856606 #define MEMPOOL_CACHE_SIZE 256
45d30ea906Sjfb8856606 
46d30ea906Sjfb8856606 /* Hardcoded K value */
47d30ea906Sjfb8856606 #define K 40
48d30ea906Sjfb8856606 #define NCB (3 * RTE_ALIGN_CEIL(K + 4, 32))
49d30ea906Sjfb8856606 
50d30ea906Sjfb8856606 #define CRC_24B_LEN 3
51d30ea906Sjfb8856606 
52d30ea906Sjfb8856606 /* Configurable number of RX/TX ring descriptors */
53d30ea906Sjfb8856606 #define RTE_TEST_RX_DESC_DEFAULT 128
54d30ea906Sjfb8856606 #define RTE_TEST_TX_DESC_DEFAULT 512
55d30ea906Sjfb8856606 
56d30ea906Sjfb8856606 #define BBDEV_ASSERT(a) do { \
57d30ea906Sjfb8856606 	if (!(a)) { \
58d30ea906Sjfb8856606 		usage(prgname); \
59d30ea906Sjfb8856606 		return -1; \
60d30ea906Sjfb8856606 	} \
61d30ea906Sjfb8856606 } while (0)
62d30ea906Sjfb8856606 
63*2d9fd380Sjfb8856606 static int input_dynfield_offset = -1;
64*2d9fd380Sjfb8856606 
65*2d9fd380Sjfb8856606 static inline struct rte_mbuf **
mbuf_input(struct rte_mbuf * mbuf)66*2d9fd380Sjfb8856606 mbuf_input(struct rte_mbuf *mbuf)
67*2d9fd380Sjfb8856606 {
68*2d9fd380Sjfb8856606 	return RTE_MBUF_DYNFIELD(mbuf,
69*2d9fd380Sjfb8856606 			input_dynfield_offset, struct rte_mbuf **);
70*2d9fd380Sjfb8856606 }
71*2d9fd380Sjfb8856606 
72d30ea906Sjfb8856606 static const struct rte_eth_conf port_conf = {
73d30ea906Sjfb8856606 	.rxmode = {
74d30ea906Sjfb8856606 		.mq_mode = ETH_MQ_RX_NONE,
754418919fSjohnjiang 		.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
76d30ea906Sjfb8856606 		.split_hdr_size = 0,
77d30ea906Sjfb8856606 	},
78d30ea906Sjfb8856606 	.txmode = {
79d30ea906Sjfb8856606 		.mq_mode = ETH_MQ_TX_NONE,
80d30ea906Sjfb8856606 	},
81d30ea906Sjfb8856606 };
82d30ea906Sjfb8856606 
83d30ea906Sjfb8856606 struct rte_bbdev_op_turbo_enc def_op_enc = {
84d30ea906Sjfb8856606 	/* These values are arbitrarily put, and does not map to the real
85d30ea906Sjfb8856606 	 * values for the data received from ethdev ports
86d30ea906Sjfb8856606 	 */
87d30ea906Sjfb8856606 	.rv_index = 0,
88d30ea906Sjfb8856606 	.code_block_mode = 1,
89d30ea906Sjfb8856606 	.cb_params = {
90d30ea906Sjfb8856606 		.k = K,
91d30ea906Sjfb8856606 	},
92d30ea906Sjfb8856606 	.op_flags = RTE_BBDEV_TURBO_CRC_24A_ATTACH
93d30ea906Sjfb8856606 };
94d30ea906Sjfb8856606 
95d30ea906Sjfb8856606 struct rte_bbdev_op_turbo_dec def_op_dec = {
96d30ea906Sjfb8856606 	/* These values are arbitrarily put, and does not map to the real
97d30ea906Sjfb8856606 	 * values for the data received from ethdev ports
98d30ea906Sjfb8856606 	 */
99d30ea906Sjfb8856606 	.code_block_mode = 1,
100d30ea906Sjfb8856606 	.cb_params = {
101d30ea906Sjfb8856606 		.k = K,
102d30ea906Sjfb8856606 	},
103d30ea906Sjfb8856606 	.rv_index = 0,
104d30ea906Sjfb8856606 	.iter_max = 8,
105d30ea906Sjfb8856606 	.iter_min = 4,
106d30ea906Sjfb8856606 	.ext_scale = 15,
107d30ea906Sjfb8856606 	.num_maps = 0,
108d30ea906Sjfb8856606 	.op_flags = RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN
109d30ea906Sjfb8856606 };
110d30ea906Sjfb8856606 
111d30ea906Sjfb8856606 struct app_config_params {
112d30ea906Sjfb8856606 	/* Placeholders for app params */
113d30ea906Sjfb8856606 	uint16_t port_id;
114d30ea906Sjfb8856606 	uint16_t bbdev_id;
115d30ea906Sjfb8856606 	uint64_t enc_core_mask;
116d30ea906Sjfb8856606 	uint64_t dec_core_mask;
117d30ea906Sjfb8856606 
118d30ea906Sjfb8856606 	/* Values filled during init time */
119d30ea906Sjfb8856606 	uint16_t enc_queue_ids[RTE_MAX_LCORE];
120d30ea906Sjfb8856606 	uint16_t dec_queue_ids[RTE_MAX_LCORE];
121d30ea906Sjfb8856606 	uint16_t num_enc_cores;
122d30ea906Sjfb8856606 	uint16_t num_dec_cores;
123d30ea906Sjfb8856606 };
124d30ea906Sjfb8856606 
125d30ea906Sjfb8856606 struct lcore_statistics {
126d30ea906Sjfb8856606 	unsigned int enqueued;
127d30ea906Sjfb8856606 	unsigned int dequeued;
128d30ea906Sjfb8856606 	unsigned int rx_lost_packets;
129d30ea906Sjfb8856606 	unsigned int enc_to_dec_lost_packets;
130d30ea906Sjfb8856606 	unsigned int tx_lost_packets;
131d30ea906Sjfb8856606 } __rte_cache_aligned;
132d30ea906Sjfb8856606 
133d30ea906Sjfb8856606 /** each lcore configuration */
134d30ea906Sjfb8856606 struct lcore_conf {
135d30ea906Sjfb8856606 	uint64_t core_type;
136d30ea906Sjfb8856606 
137d30ea906Sjfb8856606 	unsigned int port_id;
138d30ea906Sjfb8856606 	unsigned int rx_queue_id;
139d30ea906Sjfb8856606 	unsigned int tx_queue_id;
140d30ea906Sjfb8856606 
141d30ea906Sjfb8856606 	unsigned int bbdev_id;
142d30ea906Sjfb8856606 	unsigned int enc_queue_id;
143d30ea906Sjfb8856606 	unsigned int dec_queue_id;
144d30ea906Sjfb8856606 
145d30ea906Sjfb8856606 	uint8_t llr_temp_buf[NCB];
146d30ea906Sjfb8856606 
147d30ea906Sjfb8856606 	struct rte_mempool *bbdev_dec_op_pool;
148d30ea906Sjfb8856606 	struct rte_mempool *bbdev_enc_op_pool;
149d30ea906Sjfb8856606 	struct rte_mempool *enc_out_pool;
150d30ea906Sjfb8856606 	struct rte_ring *enc_to_dec_ring;
151d30ea906Sjfb8856606 
152d30ea906Sjfb8856606 	struct lcore_statistics *lcore_stats;
153d30ea906Sjfb8856606 } __rte_cache_aligned;
154d30ea906Sjfb8856606 
155d30ea906Sjfb8856606 struct stats_lcore_params {
156d30ea906Sjfb8856606 	struct lcore_conf *lconf;
157d30ea906Sjfb8856606 	struct app_config_params *app_params;
158d30ea906Sjfb8856606 };
159d30ea906Sjfb8856606 
160d30ea906Sjfb8856606 
161d30ea906Sjfb8856606 static const struct app_config_params def_app_config = {
162d30ea906Sjfb8856606 	.port_id = 0,
163d30ea906Sjfb8856606 	.bbdev_id = 0,
164d30ea906Sjfb8856606 	.enc_core_mask = 0x2,
165d30ea906Sjfb8856606 	.dec_core_mask = 0x4,
166d30ea906Sjfb8856606 	.num_enc_cores = 1,
167d30ea906Sjfb8856606 	.num_dec_cores = 1,
168d30ea906Sjfb8856606 };
169d30ea906Sjfb8856606 
170d30ea906Sjfb8856606 static rte_atomic16_t global_exit_flag;
171d30ea906Sjfb8856606 
172d30ea906Sjfb8856606 /* display usage */
173d30ea906Sjfb8856606 static inline void
usage(const char * prgname)174d30ea906Sjfb8856606 usage(const char *prgname)
175d30ea906Sjfb8856606 {
176d30ea906Sjfb8856606 	printf("%s [EAL options] "
177d30ea906Sjfb8856606 			"  --\n"
178d30ea906Sjfb8856606 			"  --enc_cores - number of encoding cores (default = 0x2)\n"
179d30ea906Sjfb8856606 			"  --dec_cores - number of decoding cores (default = 0x4)\n"
180d30ea906Sjfb8856606 			"  --port_id - Ethernet port ID (default = 0)\n"
181d30ea906Sjfb8856606 			"  --bbdev_id - BBDev ID (default = 0)\n"
182d30ea906Sjfb8856606 			"\n", prgname);
183d30ea906Sjfb8856606 }
184d30ea906Sjfb8856606 
185d30ea906Sjfb8856606 /* parse core mask */
186d30ea906Sjfb8856606 static inline
bbdev_parse_mask(const char * mask)187d30ea906Sjfb8856606 uint16_t bbdev_parse_mask(const char *mask)
188d30ea906Sjfb8856606 {
189d30ea906Sjfb8856606 	char *end = NULL;
190d30ea906Sjfb8856606 	unsigned long pm;
191d30ea906Sjfb8856606 
192d30ea906Sjfb8856606 	/* parse hexadecimal string */
193d30ea906Sjfb8856606 	pm = strtoul(mask, &end, 16);
194d30ea906Sjfb8856606 	if ((mask[0] == '\0') || (end == NULL) || (*end != '\0'))
195d30ea906Sjfb8856606 		return 0;
196d30ea906Sjfb8856606 
197d30ea906Sjfb8856606 	return pm;
198d30ea906Sjfb8856606 }
199d30ea906Sjfb8856606 
200d30ea906Sjfb8856606 /* parse core mask */
201d30ea906Sjfb8856606 static inline
bbdev_parse_number(const char * mask)202d30ea906Sjfb8856606 uint16_t bbdev_parse_number(const char *mask)
203d30ea906Sjfb8856606 {
204d30ea906Sjfb8856606 	char *end = NULL;
205d30ea906Sjfb8856606 	unsigned long pm;
206d30ea906Sjfb8856606 
207d30ea906Sjfb8856606 	/* parse hexadecimal string */
208d30ea906Sjfb8856606 	pm = strtoul(mask, &end, 10);
209d30ea906Sjfb8856606 	if ((mask[0] == '\0') || (end == NULL) || (*end != '\0'))
210d30ea906Sjfb8856606 		return 0;
211d30ea906Sjfb8856606 
212d30ea906Sjfb8856606 	return pm;
213d30ea906Sjfb8856606 }
214d30ea906Sjfb8856606 
215d30ea906Sjfb8856606 static int
bbdev_parse_args(int argc,char ** argv,struct app_config_params * app_params)216d30ea906Sjfb8856606 bbdev_parse_args(int argc, char **argv,
217d30ea906Sjfb8856606 		struct app_config_params *app_params)
218d30ea906Sjfb8856606 {
219d30ea906Sjfb8856606 	int optind = 0;
220d30ea906Sjfb8856606 	int opt;
221d30ea906Sjfb8856606 	int opt_indx = 0;
222d30ea906Sjfb8856606 	char *prgname = argv[0];
223d30ea906Sjfb8856606 
224d30ea906Sjfb8856606 	static struct option lgopts[] = {
225d30ea906Sjfb8856606 		{ "enc_core_mask", required_argument, 0, 'e' },
226d30ea906Sjfb8856606 		{ "dec_core_mask", required_argument, 0, 'd' },
227d30ea906Sjfb8856606 		{ "port_id", required_argument, 0, 'p' },
228d30ea906Sjfb8856606 		{ "bbdev_id", required_argument, 0, 'b' },
229d30ea906Sjfb8856606 		{ NULL, 0, 0, 0 }
230d30ea906Sjfb8856606 	};
231d30ea906Sjfb8856606 
232d30ea906Sjfb8856606 	BBDEV_ASSERT(argc != 0);
233d30ea906Sjfb8856606 	BBDEV_ASSERT(argv != NULL);
234d30ea906Sjfb8856606 	BBDEV_ASSERT(app_params != NULL);
235d30ea906Sjfb8856606 
236d30ea906Sjfb8856606 	while ((opt = getopt_long(argc, argv, "e:d:p:b:", lgopts, &opt_indx)) !=
237d30ea906Sjfb8856606 		EOF) {
238d30ea906Sjfb8856606 		switch (opt) {
239d30ea906Sjfb8856606 		case 'e':
240d30ea906Sjfb8856606 			app_params->enc_core_mask =
241d30ea906Sjfb8856606 				bbdev_parse_mask(optarg);
242d30ea906Sjfb8856606 			if (app_params->enc_core_mask == 0) {
243d30ea906Sjfb8856606 				usage(prgname);
244d30ea906Sjfb8856606 				return -1;
245d30ea906Sjfb8856606 			}
246d30ea906Sjfb8856606 			app_params->num_enc_cores =
247d30ea906Sjfb8856606 				__builtin_popcount(app_params->enc_core_mask);
248d30ea906Sjfb8856606 			break;
249d30ea906Sjfb8856606 
250d30ea906Sjfb8856606 		case 'd':
251d30ea906Sjfb8856606 			app_params->dec_core_mask =
252d30ea906Sjfb8856606 				bbdev_parse_mask(optarg);
253d30ea906Sjfb8856606 			if (app_params->dec_core_mask == 0) {
254d30ea906Sjfb8856606 				usage(prgname);
255d30ea906Sjfb8856606 				return -1;
256d30ea906Sjfb8856606 			}
257d30ea906Sjfb8856606 			app_params->num_dec_cores =
258d30ea906Sjfb8856606 				__builtin_popcount(app_params->dec_core_mask);
259d30ea906Sjfb8856606 			break;
260d30ea906Sjfb8856606 
261d30ea906Sjfb8856606 		case 'p':
262d30ea906Sjfb8856606 			app_params->port_id = bbdev_parse_number(optarg);
263d30ea906Sjfb8856606 			break;
264d30ea906Sjfb8856606 
265d30ea906Sjfb8856606 		case 'b':
266d30ea906Sjfb8856606 			app_params->bbdev_id = bbdev_parse_number(optarg);
267d30ea906Sjfb8856606 			break;
268d30ea906Sjfb8856606 
269d30ea906Sjfb8856606 		default:
270d30ea906Sjfb8856606 			usage(prgname);
271d30ea906Sjfb8856606 			return -1;
272d30ea906Sjfb8856606 		}
273d30ea906Sjfb8856606 	}
274d30ea906Sjfb8856606 	optind = 0;
275d30ea906Sjfb8856606 	return optind;
276d30ea906Sjfb8856606 }
277d30ea906Sjfb8856606 
278d30ea906Sjfb8856606 static void
signal_handler(int signum)279d30ea906Sjfb8856606 signal_handler(int signum)
280d30ea906Sjfb8856606 {
281d30ea906Sjfb8856606 	printf("\nSignal %d received\n", signum);
282d30ea906Sjfb8856606 	rte_atomic16_set(&global_exit_flag, 1);
283d30ea906Sjfb8856606 }
284d30ea906Sjfb8856606 
285d30ea906Sjfb8856606 static void
print_mac(unsigned int portid,struct rte_ether_addr * bbdev_ports_eth_address)2864418919fSjohnjiang print_mac(unsigned int portid, struct rte_ether_addr *bbdev_ports_eth_address)
287d30ea906Sjfb8856606 {
288d30ea906Sjfb8856606 	printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
289d30ea906Sjfb8856606 			(unsigned int) portid,
290d30ea906Sjfb8856606 			bbdev_ports_eth_address->addr_bytes[0],
291d30ea906Sjfb8856606 			bbdev_ports_eth_address->addr_bytes[1],
292d30ea906Sjfb8856606 			bbdev_ports_eth_address->addr_bytes[2],
293d30ea906Sjfb8856606 			bbdev_ports_eth_address->addr_bytes[3],
294d30ea906Sjfb8856606 			bbdev_ports_eth_address->addr_bytes[4],
295d30ea906Sjfb8856606 			bbdev_ports_eth_address->addr_bytes[5]);
296d30ea906Sjfb8856606 }
297d30ea906Sjfb8856606 
298d30ea906Sjfb8856606 static inline void
pktmbuf_free_bulk(struct rte_mbuf ** mbufs,unsigned int nb_to_free)299d30ea906Sjfb8856606 pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int nb_to_free)
300d30ea906Sjfb8856606 {
301d30ea906Sjfb8856606 	unsigned int i;
302d30ea906Sjfb8856606 	for (i = 0; i < nb_to_free; ++i)
303d30ea906Sjfb8856606 		rte_pktmbuf_free(mbufs[i]);
304d30ea906Sjfb8856606 }
305d30ea906Sjfb8856606 
306d30ea906Sjfb8856606 static inline void
pktmbuf_input_free_bulk(struct rte_mbuf ** mbufs,unsigned int nb_to_free)307*2d9fd380Sjfb8856606 pktmbuf_input_free_bulk(struct rte_mbuf **mbufs, unsigned int nb_to_free)
308d30ea906Sjfb8856606 {
309d30ea906Sjfb8856606 	unsigned int i;
310d30ea906Sjfb8856606 	for (i = 0; i < nb_to_free; ++i) {
311*2d9fd380Sjfb8856606 		struct rte_mbuf *rx_pkt = *mbuf_input(mbufs[i]);
312d30ea906Sjfb8856606 		rte_pktmbuf_free(rx_pkt);
313d30ea906Sjfb8856606 		rte_pktmbuf_free(mbufs[i]);
314d30ea906Sjfb8856606 	}
315d30ea906Sjfb8856606 }
316d30ea906Sjfb8856606 
317d30ea906Sjfb8856606 /* Check the link status of all ports in up to 9s, and print them finally */
318d30ea906Sjfb8856606 static int
check_port_link_status(uint16_t port_id)319d30ea906Sjfb8856606 check_port_link_status(uint16_t port_id)
320d30ea906Sjfb8856606 {
321d30ea906Sjfb8856606 #define CHECK_INTERVAL 100 /* 100ms */
322d30ea906Sjfb8856606 #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
323d30ea906Sjfb8856606 	uint8_t count;
324d30ea906Sjfb8856606 	struct rte_eth_link link;
3254418919fSjohnjiang 	int link_get_err = -EINVAL;
326d30ea906Sjfb8856606 
327d30ea906Sjfb8856606 	printf("\nChecking link status.");
328d30ea906Sjfb8856606 	fflush(stdout);
329d30ea906Sjfb8856606 
330d30ea906Sjfb8856606 	for (count = 0; count <= MAX_CHECK_TIME &&
331d30ea906Sjfb8856606 			!rte_atomic16_read(&global_exit_flag); count++) {
332d30ea906Sjfb8856606 		memset(&link, 0, sizeof(link));
3334418919fSjohnjiang 		link_get_err = rte_eth_link_get_nowait(port_id, &link);
334d30ea906Sjfb8856606 
3354418919fSjohnjiang 		if (link_get_err >= 0 && link.link_status) {
336d30ea906Sjfb8856606 			const char *dp = (link.link_duplex ==
337d30ea906Sjfb8856606 				ETH_LINK_FULL_DUPLEX) ?
338d30ea906Sjfb8856606 				"full-duplex" : "half-duplex";
339*2d9fd380Sjfb8856606 			printf("\nPort %u Link Up - speed %s - %s\n",
340*2d9fd380Sjfb8856606 				port_id,
341*2d9fd380Sjfb8856606 				rte_eth_link_speed_to_str(link.link_speed),
342*2d9fd380Sjfb8856606 				dp);
343d30ea906Sjfb8856606 			return 0;
344d30ea906Sjfb8856606 		}
345d30ea906Sjfb8856606 		printf(".");
346d30ea906Sjfb8856606 		fflush(stdout);
347d30ea906Sjfb8856606 		rte_delay_ms(CHECK_INTERVAL);
348d30ea906Sjfb8856606 	}
349d30ea906Sjfb8856606 
3504418919fSjohnjiang 	if (link_get_err >= 0)
351d30ea906Sjfb8856606 		printf("\nPort %d Link Down\n", port_id);
3524418919fSjohnjiang 	else
3534418919fSjohnjiang 		printf("\nGet link failed (port %d): %s\n", port_id,
3544418919fSjohnjiang 		       rte_strerror(-link_get_err));
3554418919fSjohnjiang 
356d30ea906Sjfb8856606 	return 0;
357d30ea906Sjfb8856606 }
358d30ea906Sjfb8856606 
359d30ea906Sjfb8856606 static inline void
add_ether_hdr(struct rte_mbuf * pkt_src,struct rte_mbuf * pkt_dst)360d30ea906Sjfb8856606 add_ether_hdr(struct rte_mbuf *pkt_src, struct rte_mbuf *pkt_dst)
361d30ea906Sjfb8856606 {
3624418919fSjohnjiang 	struct rte_ether_hdr *eth_from;
3634418919fSjohnjiang 	struct rte_ether_hdr *eth_to;
364d30ea906Sjfb8856606 
3654418919fSjohnjiang 	eth_from = rte_pktmbuf_mtod(pkt_src, struct rte_ether_hdr *);
3664418919fSjohnjiang 	eth_to = rte_pktmbuf_mtod(pkt_dst, struct rte_ether_hdr *);
367d30ea906Sjfb8856606 
368d30ea906Sjfb8856606 	/* copy header */
3694418919fSjohnjiang 	rte_memcpy(eth_to, eth_from, sizeof(struct rte_ether_hdr));
370d30ea906Sjfb8856606 }
371d30ea906Sjfb8856606 
372d30ea906Sjfb8856606 static inline void
add_awgn(struct rte_mbuf ** mbufs,uint16_t num_pkts)373d30ea906Sjfb8856606 add_awgn(struct rte_mbuf **mbufs, uint16_t num_pkts)
374d30ea906Sjfb8856606 {
375d30ea906Sjfb8856606 	RTE_SET_USED(mbufs);
376d30ea906Sjfb8856606 	RTE_SET_USED(num_pkts);
377d30ea906Sjfb8856606 }
378d30ea906Sjfb8856606 
379d30ea906Sjfb8856606 /* Encoder output to Decoder input adapter. The Decoder accepts only soft input
380d30ea906Sjfb8856606  * so each bit of the encoder output must be translated into one byte of LLR. If
381d30ea906Sjfb8856606  * Sub-block Deinterleaver is bypassed, which is the case, the padding bytes
382d30ea906Sjfb8856606  * must additionally be insterted at the end of each sub-block.
383d30ea906Sjfb8856606  */
384d30ea906Sjfb8856606 static inline void
transform_enc_out_dec_in(struct rte_mbuf ** mbufs,uint8_t * temp_buf,uint16_t num_pkts,uint16_t k)385d30ea906Sjfb8856606 transform_enc_out_dec_in(struct rte_mbuf **mbufs, uint8_t *temp_buf,
386d30ea906Sjfb8856606 		uint16_t num_pkts, uint16_t k)
387d30ea906Sjfb8856606 {
388d30ea906Sjfb8856606 	uint16_t i, l, j;
389d30ea906Sjfb8856606 	uint16_t start_bit_idx;
390d30ea906Sjfb8856606 	uint16_t out_idx;
391d30ea906Sjfb8856606 	uint16_t d = k + 4;
392d30ea906Sjfb8856606 	uint16_t kpi = RTE_ALIGN_CEIL(d, 32);
393d30ea906Sjfb8856606 	uint16_t nd = kpi - d;
394d30ea906Sjfb8856606 	uint16_t ncb = 3 * kpi;
395d30ea906Sjfb8856606 
396d30ea906Sjfb8856606 	for (i = 0; i < num_pkts; ++i) {
397d30ea906Sjfb8856606 		uint16_t pkt_data_len = rte_pktmbuf_data_len(mbufs[i]) -
3984418919fSjohnjiang 				sizeof(struct rte_ether_hdr);
399d30ea906Sjfb8856606 
400d30ea906Sjfb8856606 		/* Resize the packet if needed */
401d30ea906Sjfb8856606 		if (pkt_data_len < ncb) {
402d30ea906Sjfb8856606 			char *data = rte_pktmbuf_append(mbufs[i],
403d30ea906Sjfb8856606 					ncb - pkt_data_len);
404d30ea906Sjfb8856606 			if (data == NULL)
405d30ea906Sjfb8856606 				printf(
406d30ea906Sjfb8856606 					"Not enough space in decoder input packet");
407d30ea906Sjfb8856606 		}
408d30ea906Sjfb8856606 
409d30ea906Sjfb8856606 		/* Translate each bit into 1 LLR byte. */
410d30ea906Sjfb8856606 		start_bit_idx = 0;
411d30ea906Sjfb8856606 		out_idx = 0;
412d30ea906Sjfb8856606 		for (j = 0; j < 3; ++j) {
413d30ea906Sjfb8856606 			for (l = start_bit_idx; l < start_bit_idx + d; ++l) {
414d30ea906Sjfb8856606 				uint8_t *data = rte_pktmbuf_mtod_offset(
415d30ea906Sjfb8856606 					mbufs[i], uint8_t *,
4164418919fSjohnjiang 					sizeof(struct rte_ether_hdr) +
4174418919fSjohnjiang 					(l >> 3));
418d30ea906Sjfb8856606 				if (*data & (0x80 >> (l & 7)))
419d30ea906Sjfb8856606 					temp_buf[out_idx] = LLR_1_BIT;
420d30ea906Sjfb8856606 				else
421d30ea906Sjfb8856606 					temp_buf[out_idx] = LLR_0_BIT;
422d30ea906Sjfb8856606 				++out_idx;
423d30ea906Sjfb8856606 			}
424d30ea906Sjfb8856606 			/* Padding bytes should be at the end of the sub-block.
425d30ea906Sjfb8856606 			 */
426d30ea906Sjfb8856606 			memset(&temp_buf[out_idx], 0, nd);
427d30ea906Sjfb8856606 			out_idx += nd;
428d30ea906Sjfb8856606 			start_bit_idx += d;
429d30ea906Sjfb8856606 		}
430d30ea906Sjfb8856606 
431d30ea906Sjfb8856606 		rte_memcpy(rte_pktmbuf_mtod_offset(mbufs[i], uint8_t *,
4324418919fSjohnjiang 				sizeof(struct rte_ether_hdr)), temp_buf, ncb);
433d30ea906Sjfb8856606 	}
434d30ea906Sjfb8856606 }
435d30ea906Sjfb8856606 
436d30ea906Sjfb8856606 static inline void
verify_data(struct rte_mbuf ** mbufs,uint16_t num_pkts)437d30ea906Sjfb8856606 verify_data(struct rte_mbuf **mbufs, uint16_t num_pkts)
438d30ea906Sjfb8856606 {
439d30ea906Sjfb8856606 	uint16_t i;
440d30ea906Sjfb8856606 	for (i = 0; i < num_pkts; ++i) {
441d30ea906Sjfb8856606 		struct rte_mbuf *out = mbufs[i];
442*2d9fd380Sjfb8856606 		struct rte_mbuf *in = *mbuf_input(out);
443d30ea906Sjfb8856606 
444d30ea906Sjfb8856606 		if (memcmp(rte_pktmbuf_mtod_offset(in, uint8_t *,
4454418919fSjohnjiang 				sizeof(struct rte_ether_hdr)),
446d30ea906Sjfb8856606 				rte_pktmbuf_mtod_offset(out, uint8_t *,
4474418919fSjohnjiang 				sizeof(struct rte_ether_hdr)),
448d30ea906Sjfb8856606 				K / 8 - CRC_24B_LEN))
449d30ea906Sjfb8856606 			printf("Input and output buffers are not equal!\n");
450d30ea906Sjfb8856606 	}
451d30ea906Sjfb8856606 }
452d30ea906Sjfb8856606 
453d30ea906Sjfb8856606 static int
initialize_ports(struct app_config_params * app_params,struct rte_mempool * ethdev_mbuf_mempool)454d30ea906Sjfb8856606 initialize_ports(struct app_config_params *app_params,
455d30ea906Sjfb8856606 		struct rte_mempool *ethdev_mbuf_mempool)
456d30ea906Sjfb8856606 {
457d30ea906Sjfb8856606 	int ret;
458d30ea906Sjfb8856606 	uint16_t port_id = app_params->port_id;
459d30ea906Sjfb8856606 	uint16_t q;
460d30ea906Sjfb8856606 	/* ethernet addresses of ports */
4614418919fSjohnjiang 	struct rte_ether_addr bbdev_port_eth_addr;
462d30ea906Sjfb8856606 
463d30ea906Sjfb8856606 	/* initialize ports */
464d30ea906Sjfb8856606 	printf("\nInitializing port %u...\n", app_params->port_id);
465d30ea906Sjfb8856606 	ret = rte_eth_dev_configure(port_id, app_params->num_enc_cores,
466d30ea906Sjfb8856606 		app_params->num_dec_cores, &port_conf);
467d30ea906Sjfb8856606 
468d30ea906Sjfb8856606 	if (ret < 0) {
469d30ea906Sjfb8856606 		printf("Cannot configure device: err=%d, port=%u\n",
470d30ea906Sjfb8856606 			ret, port_id);
471d30ea906Sjfb8856606 		return -1;
472d30ea906Sjfb8856606 	}
473d30ea906Sjfb8856606 
474d30ea906Sjfb8856606 	/* initialize RX queues for encoder */
475d30ea906Sjfb8856606 	for (q = 0; q < app_params->num_enc_cores; q++) {
476d30ea906Sjfb8856606 		ret = rte_eth_rx_queue_setup(port_id, q,
477d30ea906Sjfb8856606 			RTE_TEST_RX_DESC_DEFAULT,
478d30ea906Sjfb8856606 			rte_eth_dev_socket_id(port_id),
479d30ea906Sjfb8856606 			NULL, ethdev_mbuf_mempool);
480d30ea906Sjfb8856606 		if (ret < 0) {
481d30ea906Sjfb8856606 			printf("rte_eth_rx_queue_setup: err=%d, queue=%u\n",
482d30ea906Sjfb8856606 				ret, q);
483d30ea906Sjfb8856606 			return -1;
484d30ea906Sjfb8856606 		}
485d30ea906Sjfb8856606 	}
486d30ea906Sjfb8856606 	/* initialize TX queues for decoder */
487d30ea906Sjfb8856606 	for (q = 0; q < app_params->num_dec_cores; q++) {
488d30ea906Sjfb8856606 		ret = rte_eth_tx_queue_setup(port_id, q,
489d30ea906Sjfb8856606 			RTE_TEST_TX_DESC_DEFAULT,
490d30ea906Sjfb8856606 			rte_eth_dev_socket_id(port_id), NULL);
491d30ea906Sjfb8856606 		if (ret < 0) {
492d30ea906Sjfb8856606 			printf("rte_eth_tx_queue_setup: err=%d, queue=%u\n",
493d30ea906Sjfb8856606 				ret, q);
494d30ea906Sjfb8856606 			return -1;
495d30ea906Sjfb8856606 		}
496d30ea906Sjfb8856606 	}
497d30ea906Sjfb8856606 
4984418919fSjohnjiang 	ret = rte_eth_promiscuous_enable(port_id);
4994418919fSjohnjiang 	if (ret != 0) {
5004418919fSjohnjiang 		printf("Cannot enable promiscuous mode: err=%s, port=%u\n",
5014418919fSjohnjiang 			rte_strerror(-ret), port_id);
5024418919fSjohnjiang 		return ret;
5034418919fSjohnjiang 	}
504d30ea906Sjfb8856606 
5054418919fSjohnjiang 	ret = rte_eth_macaddr_get(port_id, &bbdev_port_eth_addr);
5064418919fSjohnjiang 	if (ret < 0) {
5074418919fSjohnjiang 		printf("rte_eth_macaddr_get: err=%d, queue=%u\n",
5084418919fSjohnjiang 			ret, q);
5094418919fSjohnjiang 		return -1;
5104418919fSjohnjiang 	}
5114418919fSjohnjiang 
512d30ea906Sjfb8856606 	print_mac(port_id, &bbdev_port_eth_addr);
513d30ea906Sjfb8856606 
514d30ea906Sjfb8856606 	return 0;
515d30ea906Sjfb8856606 }
516d30ea906Sjfb8856606 
517d30ea906Sjfb8856606 static void
lcore_conf_init(struct app_config_params * app_params,struct lcore_conf * lcore_conf,struct rte_mempool ** bbdev_op_pools,struct rte_mempool * bbdev_mbuf_mempool,struct rte_ring * enc_to_dec_ring,struct lcore_statistics * lcore_stats)518d30ea906Sjfb8856606 lcore_conf_init(struct app_config_params *app_params,
519d30ea906Sjfb8856606 		struct lcore_conf *lcore_conf,
520d30ea906Sjfb8856606 		struct rte_mempool **bbdev_op_pools,
521d30ea906Sjfb8856606 		struct rte_mempool *bbdev_mbuf_mempool,
522d30ea906Sjfb8856606 		struct rte_ring *enc_to_dec_ring,
523d30ea906Sjfb8856606 		struct lcore_statistics *lcore_stats)
524d30ea906Sjfb8856606 {
525d30ea906Sjfb8856606 	unsigned int lcore_id;
526d30ea906Sjfb8856606 	struct lcore_conf *lconf;
527d30ea906Sjfb8856606 	uint16_t rx_queue_id = 0;
528d30ea906Sjfb8856606 	uint16_t tx_queue_id = 0;
529d30ea906Sjfb8856606 	uint16_t enc_q_id = 0;
530d30ea906Sjfb8856606 	uint16_t dec_q_id = 0;
531d30ea906Sjfb8856606 
532d30ea906Sjfb8856606 	/* Configure lcores */
533d30ea906Sjfb8856606 	for (lcore_id = 0; lcore_id < 8 * sizeof(uint64_t); ++lcore_id) {
534d30ea906Sjfb8856606 		lconf = &lcore_conf[lcore_id];
535d30ea906Sjfb8856606 		lconf->core_type = 0;
536d30ea906Sjfb8856606 
537d30ea906Sjfb8856606 		if ((1ULL << lcore_id) & app_params->enc_core_mask) {
538d30ea906Sjfb8856606 			lconf->core_type |= (1 << RTE_BBDEV_OP_TURBO_ENC);
539d30ea906Sjfb8856606 			lconf->rx_queue_id = rx_queue_id++;
540d30ea906Sjfb8856606 			lconf->enc_queue_id =
541d30ea906Sjfb8856606 					app_params->enc_queue_ids[enc_q_id++];
542d30ea906Sjfb8856606 		}
543d30ea906Sjfb8856606 
544d30ea906Sjfb8856606 		if ((1ULL << lcore_id) & app_params->dec_core_mask) {
545d30ea906Sjfb8856606 			lconf->core_type |= (1 << RTE_BBDEV_OP_TURBO_DEC);
546d30ea906Sjfb8856606 			lconf->tx_queue_id = tx_queue_id++;
547d30ea906Sjfb8856606 			lconf->dec_queue_id =
548d30ea906Sjfb8856606 					app_params->dec_queue_ids[dec_q_id++];
549d30ea906Sjfb8856606 		}
550d30ea906Sjfb8856606 
551d30ea906Sjfb8856606 		lconf->bbdev_enc_op_pool =
552d30ea906Sjfb8856606 				bbdev_op_pools[RTE_BBDEV_OP_TURBO_ENC];
553d30ea906Sjfb8856606 		lconf->bbdev_dec_op_pool =
554d30ea906Sjfb8856606 				bbdev_op_pools[RTE_BBDEV_OP_TURBO_DEC];
555d30ea906Sjfb8856606 		lconf->bbdev_id = app_params->bbdev_id;
556d30ea906Sjfb8856606 		lconf->port_id = app_params->port_id;
557d30ea906Sjfb8856606 		lconf->enc_out_pool = bbdev_mbuf_mempool;
558d30ea906Sjfb8856606 		lconf->enc_to_dec_ring = enc_to_dec_ring;
559d30ea906Sjfb8856606 		lconf->lcore_stats = &lcore_stats[lcore_id];
560d30ea906Sjfb8856606 	}
561d30ea906Sjfb8856606 }
562d30ea906Sjfb8856606 
563d30ea906Sjfb8856606 static void
print_lcore_stats(struct lcore_statistics * lstats,unsigned int lcore_id)564d30ea906Sjfb8856606 print_lcore_stats(struct lcore_statistics *lstats, unsigned int lcore_id)
565d30ea906Sjfb8856606 {
566d30ea906Sjfb8856606 	static const char *stats_border = "_______";
567d30ea906Sjfb8856606 
568d30ea906Sjfb8856606 	printf("\nLcore %d: %s enqueued count:\t\t%u\n",
569d30ea906Sjfb8856606 			lcore_id, stats_border, lstats->enqueued);
570d30ea906Sjfb8856606 	printf("Lcore %d: %s dequeued count:\t\t%u\n",
571d30ea906Sjfb8856606 			lcore_id, stats_border, lstats->dequeued);
572d30ea906Sjfb8856606 	printf("Lcore %d: %s RX lost packets count:\t\t%u\n",
573d30ea906Sjfb8856606 			lcore_id, stats_border, lstats->rx_lost_packets);
574d30ea906Sjfb8856606 	printf("Lcore %d: %s encoder-to-decoder lost count:\t%u\n",
575d30ea906Sjfb8856606 			lcore_id, stats_border,
576d30ea906Sjfb8856606 			lstats->enc_to_dec_lost_packets);
577d30ea906Sjfb8856606 	printf("Lcore %d: %s TX lost packets count:\t\t%u\n",
578d30ea906Sjfb8856606 			lcore_id, stats_border, lstats->tx_lost_packets);
579d30ea906Sjfb8856606 }
580d30ea906Sjfb8856606 
581d30ea906Sjfb8856606 static void
print_stats(struct stats_lcore_params * stats_lcore)582d30ea906Sjfb8856606 print_stats(struct stats_lcore_params *stats_lcore)
583d30ea906Sjfb8856606 {
584d30ea906Sjfb8856606 	unsigned int l_id;
585d30ea906Sjfb8856606 	unsigned int bbdev_id = stats_lcore->app_params->bbdev_id;
586d30ea906Sjfb8856606 	unsigned int port_id = stats_lcore->app_params->port_id;
587d30ea906Sjfb8856606 	int len, ret, i;
588d30ea906Sjfb8856606 
589d30ea906Sjfb8856606 	struct rte_eth_xstat *xstats;
590d30ea906Sjfb8856606 	struct rte_eth_xstat_name *xstats_names;
591d30ea906Sjfb8856606 	struct rte_bbdev_stats bbstats;
592d30ea906Sjfb8856606 	static const char *stats_border = "_______";
593d30ea906Sjfb8856606 
594d30ea906Sjfb8856606 	const char clr[] = { 27, '[', '2', 'J', '\0' };
595d30ea906Sjfb8856606 	const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
596d30ea906Sjfb8856606 
597d30ea906Sjfb8856606 	/* Clear screen and move to top left */
598d30ea906Sjfb8856606 	printf("%s%s", clr, topLeft);
599d30ea906Sjfb8856606 
600d30ea906Sjfb8856606 	printf("PORT STATISTICS:\n================\n");
601d30ea906Sjfb8856606 	len = rte_eth_xstats_get(port_id, NULL, 0);
602d30ea906Sjfb8856606 	if (len < 0)
603d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
604d30ea906Sjfb8856606 				"rte_eth_xstats_get(%u) failed: %d", port_id,
605d30ea906Sjfb8856606 				len);
606d30ea906Sjfb8856606 
607d30ea906Sjfb8856606 	xstats = calloc(len, sizeof(*xstats));
608d30ea906Sjfb8856606 	if (xstats == NULL)
609d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
610d30ea906Sjfb8856606 				"Failed to calloc memory for xstats");
611d30ea906Sjfb8856606 
612d30ea906Sjfb8856606 	ret = rte_eth_xstats_get(port_id, xstats, len);
613d30ea906Sjfb8856606 	if (ret < 0 || ret > len) {
614d30ea906Sjfb8856606 		free(xstats);
615d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
616d30ea906Sjfb8856606 				"rte_eth_xstats_get(%u) len%i failed: %d",
617d30ea906Sjfb8856606 				port_id, len, ret);
618d30ea906Sjfb8856606 	}
619d30ea906Sjfb8856606 
620d30ea906Sjfb8856606 	xstats_names = calloc(len, sizeof(*xstats_names));
621d30ea906Sjfb8856606 	if (xstats_names == NULL) {
622d30ea906Sjfb8856606 		free(xstats);
623d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
624d30ea906Sjfb8856606 				"Failed to calloc memory for xstats_names");
625d30ea906Sjfb8856606 	}
626d30ea906Sjfb8856606 
627d30ea906Sjfb8856606 	ret = rte_eth_xstats_get_names(port_id, xstats_names, len);
628d30ea906Sjfb8856606 	if (ret < 0 || ret > len) {
629d30ea906Sjfb8856606 		free(xstats);
630d30ea906Sjfb8856606 		free(xstats_names);
631d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
632d30ea906Sjfb8856606 				"rte_eth_xstats_get_names(%u) len%i failed: %d",
633d30ea906Sjfb8856606 				port_id, len, ret);
634d30ea906Sjfb8856606 	}
635d30ea906Sjfb8856606 
636d30ea906Sjfb8856606 	for (i = 0; i < len; i++) {
637d30ea906Sjfb8856606 		if (xstats[i].value > 0)
638d30ea906Sjfb8856606 			printf("Port %u: %s %s:\t\t%"PRIu64"\n",
639d30ea906Sjfb8856606 					port_id, stats_border,
640d30ea906Sjfb8856606 					xstats_names[i].name,
641d30ea906Sjfb8856606 					xstats[i].value);
642d30ea906Sjfb8856606 	}
643d30ea906Sjfb8856606 
644d30ea906Sjfb8856606 	ret = rte_bbdev_stats_get(bbdev_id, &bbstats);
645d30ea906Sjfb8856606 	if (ret < 0) {
646d30ea906Sjfb8856606 		free(xstats);
647d30ea906Sjfb8856606 		free(xstats_names);
648d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
649d30ea906Sjfb8856606 				"ERROR(%d): Failure to get BBDEV %u statistics\n",
650d30ea906Sjfb8856606 				ret, bbdev_id);
651d30ea906Sjfb8856606 	}
652d30ea906Sjfb8856606 
653d30ea906Sjfb8856606 	printf("\nBBDEV STATISTICS:\n=================\n");
654d30ea906Sjfb8856606 	printf("BBDEV %u: %s enqueue count:\t\t%"PRIu64"\n",
655d30ea906Sjfb8856606 			bbdev_id, stats_border,
656d30ea906Sjfb8856606 			bbstats.enqueued_count);
657d30ea906Sjfb8856606 	printf("BBDEV %u: %s dequeue count:\t\t%"PRIu64"\n",
658d30ea906Sjfb8856606 			bbdev_id, stats_border,
659d30ea906Sjfb8856606 			bbstats.dequeued_count);
660d30ea906Sjfb8856606 	printf("BBDEV %u: %s enqueue error count:\t\t%"PRIu64"\n",
661d30ea906Sjfb8856606 			bbdev_id, stats_border,
662d30ea906Sjfb8856606 			bbstats.enqueue_err_count);
663d30ea906Sjfb8856606 	printf("BBDEV %u: %s dequeue error count:\t\t%"PRIu64"\n\n",
664d30ea906Sjfb8856606 			bbdev_id, stats_border,
665d30ea906Sjfb8856606 			bbstats.dequeue_err_count);
666d30ea906Sjfb8856606 
667d30ea906Sjfb8856606 	printf("LCORE STATISTICS:\n=================\n");
668d30ea906Sjfb8856606 	for (l_id = 0; l_id < RTE_MAX_LCORE; ++l_id) {
669d30ea906Sjfb8856606 		if (stats_lcore->lconf[l_id].core_type == 0)
670d30ea906Sjfb8856606 			continue;
671d30ea906Sjfb8856606 		print_lcore_stats(stats_lcore->lconf[l_id].lcore_stats, l_id);
672d30ea906Sjfb8856606 	}
673d30ea906Sjfb8856606 
6740c6bd470Sfengbojiang 	fflush(stdout);
6750c6bd470Sfengbojiang 
676d30ea906Sjfb8856606 	free(xstats);
677d30ea906Sjfb8856606 	free(xstats_names);
678d30ea906Sjfb8856606 }
679d30ea906Sjfb8856606 
680d30ea906Sjfb8856606 static int
stats_loop(void * arg)681d30ea906Sjfb8856606 stats_loop(void *arg)
682d30ea906Sjfb8856606 {
683d30ea906Sjfb8856606 	struct stats_lcore_params *stats_lcore = arg;
684d30ea906Sjfb8856606 
685d30ea906Sjfb8856606 	while (!rte_atomic16_read(&global_exit_flag)) {
686d30ea906Sjfb8856606 		print_stats(stats_lcore);
687d30ea906Sjfb8856606 		rte_delay_ms(500);
688d30ea906Sjfb8856606 	}
689d30ea906Sjfb8856606 
690d30ea906Sjfb8856606 	return 0;
691d30ea906Sjfb8856606 }
692d30ea906Sjfb8856606 
693d30ea906Sjfb8856606 static inline void
run_encoding(struct lcore_conf * lcore_conf)694d30ea906Sjfb8856606 run_encoding(struct lcore_conf *lcore_conf)
695d30ea906Sjfb8856606 {
696d30ea906Sjfb8856606 	uint16_t i;
697d30ea906Sjfb8856606 	uint16_t port_id, rx_queue_id;
698d30ea906Sjfb8856606 	uint16_t bbdev_id, enc_queue_id;
699d30ea906Sjfb8856606 	uint16_t nb_rx, nb_enq, nb_deq, nb_sent;
700d30ea906Sjfb8856606 	struct rte_mbuf *rx_pkts_burst[MAX_PKT_BURST];
701d30ea906Sjfb8856606 	struct rte_mbuf *enc_out_pkts[MAX_PKT_BURST];
702d30ea906Sjfb8856606 	struct rte_bbdev_enc_op *bbdev_ops_burst[MAX_PKT_BURST];
703d30ea906Sjfb8856606 	struct lcore_statistics *lcore_stats;
704d30ea906Sjfb8856606 	struct rte_mempool *bbdev_op_pool, *enc_out_pool;
705d30ea906Sjfb8856606 	struct rte_ring *enc_to_dec_ring;
706d30ea906Sjfb8856606 	const int in_data_len = (def_op_enc.cb_params.k / 8) - CRC_24B_LEN;
707d30ea906Sjfb8856606 
708d30ea906Sjfb8856606 	lcore_stats = lcore_conf->lcore_stats;
709d30ea906Sjfb8856606 	port_id = lcore_conf->port_id;
710d30ea906Sjfb8856606 	rx_queue_id = lcore_conf->rx_queue_id;
711d30ea906Sjfb8856606 	bbdev_id = lcore_conf->bbdev_id;
712d30ea906Sjfb8856606 	enc_queue_id = lcore_conf->enc_queue_id;
713d30ea906Sjfb8856606 	bbdev_op_pool = lcore_conf->bbdev_enc_op_pool;
714d30ea906Sjfb8856606 	enc_out_pool = lcore_conf->enc_out_pool;
715d30ea906Sjfb8856606 	enc_to_dec_ring = lcore_conf->enc_to_dec_ring;
716d30ea906Sjfb8856606 
717d30ea906Sjfb8856606 	/* Read packet from RX queues*/
718d30ea906Sjfb8856606 	nb_rx = rte_eth_rx_burst(port_id, rx_queue_id, rx_pkts_burst,
719d30ea906Sjfb8856606 			MAX_PKT_BURST);
720d30ea906Sjfb8856606 	if (!nb_rx)
721d30ea906Sjfb8856606 		return;
722d30ea906Sjfb8856606 
723d30ea906Sjfb8856606 	if (unlikely(rte_mempool_get_bulk(enc_out_pool, (void **)enc_out_pkts,
724d30ea906Sjfb8856606 			nb_rx) != 0)) {
725d30ea906Sjfb8856606 		pktmbuf_free_bulk(rx_pkts_burst, nb_rx);
726d30ea906Sjfb8856606 		lcore_stats->rx_lost_packets += nb_rx;
727d30ea906Sjfb8856606 		return;
728d30ea906Sjfb8856606 	}
729d30ea906Sjfb8856606 
730d30ea906Sjfb8856606 	if (unlikely(rte_bbdev_enc_op_alloc_bulk(bbdev_op_pool, bbdev_ops_burst,
731d30ea906Sjfb8856606 			nb_rx) != 0)) {
732d30ea906Sjfb8856606 		pktmbuf_free_bulk(enc_out_pkts, nb_rx);
733d30ea906Sjfb8856606 		pktmbuf_free_bulk(rx_pkts_burst, nb_rx);
734d30ea906Sjfb8856606 		lcore_stats->rx_lost_packets += nb_rx;
735d30ea906Sjfb8856606 		return;
736d30ea906Sjfb8856606 	}
737d30ea906Sjfb8856606 
738d30ea906Sjfb8856606 	for (i = 0; i < nb_rx; i++) {
739d30ea906Sjfb8856606 		char *data;
740d30ea906Sjfb8856606 		const uint16_t pkt_data_len =
741d30ea906Sjfb8856606 				rte_pktmbuf_data_len(rx_pkts_burst[i]) -
7424418919fSjohnjiang 				sizeof(struct rte_ether_hdr);
743d30ea906Sjfb8856606 		/* save input mbuf pointer for later comparison */
744*2d9fd380Sjfb8856606 		*mbuf_input(enc_out_pkts[i]) = rx_pkts_burst[i];
745d30ea906Sjfb8856606 
746d30ea906Sjfb8856606 		/* copy ethernet header */
747d30ea906Sjfb8856606 		rte_pktmbuf_reset(enc_out_pkts[i]);
748d30ea906Sjfb8856606 		data = rte_pktmbuf_append(enc_out_pkts[i],
7494418919fSjohnjiang 				sizeof(struct rte_ether_hdr));
750d30ea906Sjfb8856606 		if (data == NULL) {
751d30ea906Sjfb8856606 			printf(
752d30ea906Sjfb8856606 				"Not enough space for ethernet header in encoder output mbuf\n");
753d30ea906Sjfb8856606 			continue;
754d30ea906Sjfb8856606 		}
755d30ea906Sjfb8856606 		add_ether_hdr(rx_pkts_burst[i], enc_out_pkts[i]);
756d30ea906Sjfb8856606 
757d30ea906Sjfb8856606 		/* set op */
758d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_enc = def_op_enc;
759d30ea906Sjfb8856606 
760d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_enc.input.data =
761d30ea906Sjfb8856606 				rx_pkts_burst[i];
762d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_enc.input.offset =
7634418919fSjohnjiang 				sizeof(struct rte_ether_hdr);
764d30ea906Sjfb8856606 		/* Encoder will attach the CRC24B, adjust the length */
765d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_enc.input.length = in_data_len;
766d30ea906Sjfb8856606 
767d30ea906Sjfb8856606 		if (in_data_len < pkt_data_len)
768d30ea906Sjfb8856606 			rte_pktmbuf_trim(rx_pkts_burst[i], pkt_data_len -
769d30ea906Sjfb8856606 					in_data_len);
770d30ea906Sjfb8856606 		else if (in_data_len > pkt_data_len) {
771d30ea906Sjfb8856606 			data = rte_pktmbuf_append(rx_pkts_burst[i],
772d30ea906Sjfb8856606 					in_data_len - pkt_data_len);
773d30ea906Sjfb8856606 			if (data == NULL)
774d30ea906Sjfb8856606 				printf(
775d30ea906Sjfb8856606 					"Not enough storage in mbuf to perform the encoding\n");
776d30ea906Sjfb8856606 		}
777d30ea906Sjfb8856606 
778d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_enc.output.data =
779d30ea906Sjfb8856606 				enc_out_pkts[i];
780d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_enc.output.offset =
7814418919fSjohnjiang 				sizeof(struct rte_ether_hdr);
782d30ea906Sjfb8856606 	}
783d30ea906Sjfb8856606 
784d30ea906Sjfb8856606 	/* Enqueue packets on BBDevice */
785d30ea906Sjfb8856606 	nb_enq = rte_bbdev_enqueue_enc_ops(bbdev_id, enc_queue_id,
786d30ea906Sjfb8856606 			bbdev_ops_burst, nb_rx);
787d30ea906Sjfb8856606 	if (unlikely(nb_enq < nb_rx)) {
788*2d9fd380Sjfb8856606 		pktmbuf_input_free_bulk(&enc_out_pkts[nb_enq],
789d30ea906Sjfb8856606 				nb_rx - nb_enq);
790d30ea906Sjfb8856606 		rte_bbdev_enc_op_free_bulk(&bbdev_ops_burst[nb_enq],
791d30ea906Sjfb8856606 				nb_rx - nb_enq);
792d30ea906Sjfb8856606 		lcore_stats->rx_lost_packets += nb_rx - nb_enq;
793d30ea906Sjfb8856606 
794d30ea906Sjfb8856606 		if (!nb_enq)
795d30ea906Sjfb8856606 			return;
796d30ea906Sjfb8856606 	}
797d30ea906Sjfb8856606 
798d30ea906Sjfb8856606 	lcore_stats->enqueued += nb_enq;
799d30ea906Sjfb8856606 
800d30ea906Sjfb8856606 	/* Dequeue packets from bbdev device*/
801d30ea906Sjfb8856606 	nb_deq = 0;
802d30ea906Sjfb8856606 	do {
803d30ea906Sjfb8856606 		nb_deq += rte_bbdev_dequeue_enc_ops(bbdev_id, enc_queue_id,
804d30ea906Sjfb8856606 				&bbdev_ops_burst[nb_deq], nb_enq - nb_deq);
805d30ea906Sjfb8856606 	} while (unlikely(nb_deq < nb_enq));
806d30ea906Sjfb8856606 
807d30ea906Sjfb8856606 	lcore_stats->dequeued += nb_deq;
808d30ea906Sjfb8856606 
809d30ea906Sjfb8856606 	/* Generate and add AWGN */
810d30ea906Sjfb8856606 	add_awgn(enc_out_pkts, nb_deq);
811d30ea906Sjfb8856606 
812d30ea906Sjfb8856606 	rte_bbdev_enc_op_free_bulk(bbdev_ops_burst, nb_deq);
813d30ea906Sjfb8856606 
814d30ea906Sjfb8856606 	/* Enqueue packets to encoder-to-decoder ring */
815d30ea906Sjfb8856606 	nb_sent = rte_ring_enqueue_burst(enc_to_dec_ring, (void **)enc_out_pkts,
816d30ea906Sjfb8856606 			nb_deq, NULL);
817d30ea906Sjfb8856606 	if (unlikely(nb_sent < nb_deq)) {
818*2d9fd380Sjfb8856606 		pktmbuf_input_free_bulk(&enc_out_pkts[nb_sent],
819d30ea906Sjfb8856606 				nb_deq - nb_sent);
820d30ea906Sjfb8856606 		lcore_stats->enc_to_dec_lost_packets += nb_deq - nb_sent;
821d30ea906Sjfb8856606 	}
822d30ea906Sjfb8856606 }
823d30ea906Sjfb8856606 
824d30ea906Sjfb8856606 static void
run_decoding(struct lcore_conf * lcore_conf)825d30ea906Sjfb8856606 run_decoding(struct lcore_conf *lcore_conf)
826d30ea906Sjfb8856606 {
827d30ea906Sjfb8856606 	uint16_t i;
828d30ea906Sjfb8856606 	uint16_t port_id, tx_queue_id;
829d30ea906Sjfb8856606 	uint16_t bbdev_id, bbdev_queue_id;
830d30ea906Sjfb8856606 	uint16_t nb_recv, nb_enq, nb_deq, nb_tx;
831d30ea906Sjfb8856606 	uint8_t *llr_temp_buf;
832d30ea906Sjfb8856606 	struct rte_mbuf *recv_pkts_burst[MAX_PKT_BURST];
833d30ea906Sjfb8856606 	struct rte_bbdev_dec_op *bbdev_ops_burst[MAX_PKT_BURST];
834d30ea906Sjfb8856606 	struct lcore_statistics *lcore_stats;
835d30ea906Sjfb8856606 	struct rte_mempool *bbdev_op_pool;
836d30ea906Sjfb8856606 	struct rte_ring *enc_to_dec_ring;
837d30ea906Sjfb8856606 
838d30ea906Sjfb8856606 	lcore_stats = lcore_conf->lcore_stats;
839d30ea906Sjfb8856606 	port_id = lcore_conf->port_id;
840d30ea906Sjfb8856606 	tx_queue_id = lcore_conf->tx_queue_id;
841d30ea906Sjfb8856606 	bbdev_id = lcore_conf->bbdev_id;
842d30ea906Sjfb8856606 	bbdev_queue_id = lcore_conf->dec_queue_id;
843d30ea906Sjfb8856606 	bbdev_op_pool = lcore_conf->bbdev_dec_op_pool;
844d30ea906Sjfb8856606 	enc_to_dec_ring = lcore_conf->enc_to_dec_ring;
845d30ea906Sjfb8856606 	llr_temp_buf = lcore_conf->llr_temp_buf;
846d30ea906Sjfb8856606 
847d30ea906Sjfb8856606 	/* Dequeue packets from the ring */
848d30ea906Sjfb8856606 	nb_recv = rte_ring_dequeue_burst(enc_to_dec_ring,
849d30ea906Sjfb8856606 			(void **)recv_pkts_burst, MAX_PKT_BURST, NULL);
850d30ea906Sjfb8856606 	if (!nb_recv)
851d30ea906Sjfb8856606 		return;
852d30ea906Sjfb8856606 
853d30ea906Sjfb8856606 	if (unlikely(rte_bbdev_dec_op_alloc_bulk(bbdev_op_pool, bbdev_ops_burst,
854d30ea906Sjfb8856606 			nb_recv) != 0)) {
855*2d9fd380Sjfb8856606 		pktmbuf_input_free_bulk(recv_pkts_burst, nb_recv);
856d30ea906Sjfb8856606 		lcore_stats->rx_lost_packets += nb_recv;
857d30ea906Sjfb8856606 		return;
858d30ea906Sjfb8856606 	}
859d30ea906Sjfb8856606 
860d30ea906Sjfb8856606 	transform_enc_out_dec_in(recv_pkts_burst, llr_temp_buf, nb_recv,
861d30ea906Sjfb8856606 			def_op_dec.cb_params.k);
862d30ea906Sjfb8856606 
863d30ea906Sjfb8856606 	for (i = 0; i < nb_recv; i++) {
864d30ea906Sjfb8856606 		/* set op */
865d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_dec = def_op_dec;
866d30ea906Sjfb8856606 
867d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_dec.input.data = recv_pkts_burst[i];
868d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_dec.input.offset =
8694418919fSjohnjiang 				sizeof(struct rte_ether_hdr);
870d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_dec.input.length =
871d30ea906Sjfb8856606 				rte_pktmbuf_data_len(recv_pkts_burst[i])
8724418919fSjohnjiang 				- sizeof(struct rte_ether_hdr);
873d30ea906Sjfb8856606 
874d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_dec.hard_output.data =
875d30ea906Sjfb8856606 				recv_pkts_burst[i];
876d30ea906Sjfb8856606 		bbdev_ops_burst[i]->turbo_dec.hard_output.offset =
8774418919fSjohnjiang 				sizeof(struct rte_ether_hdr);
878d30ea906Sjfb8856606 	}
879d30ea906Sjfb8856606 
880d30ea906Sjfb8856606 	/* Enqueue packets on BBDevice */
881d30ea906Sjfb8856606 	nb_enq = rte_bbdev_enqueue_dec_ops(bbdev_id, bbdev_queue_id,
882d30ea906Sjfb8856606 			bbdev_ops_burst, nb_recv);
883d30ea906Sjfb8856606 	if (unlikely(nb_enq < nb_recv)) {
884*2d9fd380Sjfb8856606 		pktmbuf_input_free_bulk(&recv_pkts_burst[nb_enq],
885d30ea906Sjfb8856606 				nb_recv - nb_enq);
886d30ea906Sjfb8856606 		rte_bbdev_dec_op_free_bulk(&bbdev_ops_burst[nb_enq],
887d30ea906Sjfb8856606 				nb_recv - nb_enq);
888d30ea906Sjfb8856606 		lcore_stats->rx_lost_packets += nb_recv - nb_enq;
889d30ea906Sjfb8856606 
890d30ea906Sjfb8856606 		if (!nb_enq)
891d30ea906Sjfb8856606 			return;
892d30ea906Sjfb8856606 	}
893d30ea906Sjfb8856606 
894d30ea906Sjfb8856606 	lcore_stats->enqueued += nb_enq;
895d30ea906Sjfb8856606 
896d30ea906Sjfb8856606 	/* Dequeue packets from BBDevice */
897d30ea906Sjfb8856606 	nb_deq = 0;
898d30ea906Sjfb8856606 	do {
899d30ea906Sjfb8856606 		nb_deq += rte_bbdev_dequeue_dec_ops(bbdev_id, bbdev_queue_id,
900d30ea906Sjfb8856606 				&bbdev_ops_burst[nb_deq], nb_enq - nb_deq);
901d30ea906Sjfb8856606 	} while (unlikely(nb_deq < nb_enq));
902d30ea906Sjfb8856606 
903d30ea906Sjfb8856606 	lcore_stats->dequeued += nb_deq;
904d30ea906Sjfb8856606 
905d30ea906Sjfb8856606 	rte_bbdev_dec_op_free_bulk(bbdev_ops_burst, nb_deq);
906d30ea906Sjfb8856606 
907d30ea906Sjfb8856606 	verify_data(recv_pkts_burst, nb_deq);
908d30ea906Sjfb8856606 
909d30ea906Sjfb8856606 	/* Free the RX mbufs after verification */
910d30ea906Sjfb8856606 	for (i = 0; i < nb_deq; ++i)
911*2d9fd380Sjfb8856606 		rte_pktmbuf_free(*mbuf_input(recv_pkts_burst[i]));
912d30ea906Sjfb8856606 
913d30ea906Sjfb8856606 	/* Transmit the packets */
914d30ea906Sjfb8856606 	nb_tx = rte_eth_tx_burst(port_id, tx_queue_id, recv_pkts_burst, nb_deq);
915d30ea906Sjfb8856606 	if (unlikely(nb_tx < nb_deq)) {
916*2d9fd380Sjfb8856606 		pktmbuf_input_free_bulk(&recv_pkts_burst[nb_tx],
917d30ea906Sjfb8856606 				nb_deq - nb_tx);
918d30ea906Sjfb8856606 		lcore_stats->tx_lost_packets += nb_deq - nb_tx;
919d30ea906Sjfb8856606 	}
920d30ea906Sjfb8856606 }
921d30ea906Sjfb8856606 
922d30ea906Sjfb8856606 static int
processing_loop(void * arg)923d30ea906Sjfb8856606 processing_loop(void *arg)
924d30ea906Sjfb8856606 {
925d30ea906Sjfb8856606 	struct lcore_conf *lcore_conf = arg;
926d30ea906Sjfb8856606 	const bool run_encoder = (lcore_conf->core_type &
927d30ea906Sjfb8856606 			(1 << RTE_BBDEV_OP_TURBO_ENC));
928d30ea906Sjfb8856606 	const bool run_decoder = (lcore_conf->core_type &
929d30ea906Sjfb8856606 			(1 << RTE_BBDEV_OP_TURBO_DEC));
930d30ea906Sjfb8856606 
931d30ea906Sjfb8856606 	while (!rte_atomic16_read(&global_exit_flag)) {
932d30ea906Sjfb8856606 		if (run_encoder)
933d30ea906Sjfb8856606 			run_encoding(lcore_conf);
934d30ea906Sjfb8856606 		if (run_decoder)
935d30ea906Sjfb8856606 			run_decoding(lcore_conf);
936d30ea906Sjfb8856606 	}
937d30ea906Sjfb8856606 
938d30ea906Sjfb8856606 	return 0;
939d30ea906Sjfb8856606 }
940d30ea906Sjfb8856606 
941d30ea906Sjfb8856606 static int
prepare_bbdev_device(unsigned int dev_id,struct rte_bbdev_info * info,struct app_config_params * app_params)942d30ea906Sjfb8856606 prepare_bbdev_device(unsigned int dev_id, struct rte_bbdev_info *info,
943d30ea906Sjfb8856606 		struct app_config_params *app_params)
944d30ea906Sjfb8856606 {
945d30ea906Sjfb8856606 	int ret;
946d30ea906Sjfb8856606 	unsigned int q_id, dec_q_id, enc_q_id;
947d30ea906Sjfb8856606 	struct rte_bbdev_queue_conf qconf = {0};
948d30ea906Sjfb8856606 	uint16_t dec_qs_nb = app_params->num_dec_cores;
949d30ea906Sjfb8856606 	uint16_t enc_qs_nb = app_params->num_enc_cores;
950d30ea906Sjfb8856606 	uint16_t tot_qs = dec_qs_nb + enc_qs_nb;
951d30ea906Sjfb8856606 
952d30ea906Sjfb8856606 	ret = rte_bbdev_setup_queues(dev_id, tot_qs, info->socket_id);
953d30ea906Sjfb8856606 	if (ret < 0)
954d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
955d30ea906Sjfb8856606 				"ERROR(%d): BBDEV %u not configured properly\n",
956d30ea906Sjfb8856606 				ret, dev_id);
957d30ea906Sjfb8856606 
958d30ea906Sjfb8856606 	/* setup device DEC queues */
959d30ea906Sjfb8856606 	qconf.socket = info->socket_id;
960d30ea906Sjfb8856606 	qconf.queue_size = info->drv.queue_size_lim;
961d30ea906Sjfb8856606 	qconf.op_type = RTE_BBDEV_OP_TURBO_DEC;
962d30ea906Sjfb8856606 
963d30ea906Sjfb8856606 	for (q_id = 0, dec_q_id = 0; q_id < dec_qs_nb; q_id++) {
964d30ea906Sjfb8856606 		ret = rte_bbdev_queue_configure(dev_id, q_id, &qconf);
965d30ea906Sjfb8856606 		if (ret < 0)
966d30ea906Sjfb8856606 			rte_exit(EXIT_FAILURE,
967d30ea906Sjfb8856606 					"ERROR(%d): BBDEV %u DEC queue %u not configured properly\n",
968d30ea906Sjfb8856606 					ret, dev_id, q_id);
969d30ea906Sjfb8856606 		app_params->dec_queue_ids[dec_q_id++] = q_id;
970d30ea906Sjfb8856606 	}
971d30ea906Sjfb8856606 
972d30ea906Sjfb8856606 	/* setup device ENC queues */
973d30ea906Sjfb8856606 	qconf.op_type = RTE_BBDEV_OP_TURBO_ENC;
974d30ea906Sjfb8856606 
975d30ea906Sjfb8856606 	for (q_id = dec_qs_nb, enc_q_id = 0; q_id < tot_qs; q_id++) {
976d30ea906Sjfb8856606 		ret = rte_bbdev_queue_configure(dev_id, q_id, &qconf);
977d30ea906Sjfb8856606 		if (ret < 0)
978d30ea906Sjfb8856606 			rte_exit(EXIT_FAILURE,
979d30ea906Sjfb8856606 					"ERROR(%d): BBDEV %u ENC queue %u not configured properly\n",
980d30ea906Sjfb8856606 					ret, dev_id, q_id);
981d30ea906Sjfb8856606 		app_params->enc_queue_ids[enc_q_id++] = q_id;
982d30ea906Sjfb8856606 	}
983d30ea906Sjfb8856606 
984d30ea906Sjfb8856606 	ret = rte_bbdev_start(dev_id);
985d30ea906Sjfb8856606 
986d30ea906Sjfb8856606 	if (ret != 0)
987d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "ERROR(%d): BBDEV %u not started\n",
988d30ea906Sjfb8856606 			ret, dev_id);
989d30ea906Sjfb8856606 
990d30ea906Sjfb8856606 	printf("BBdev %u started\n", dev_id);
991d30ea906Sjfb8856606 
992d30ea906Sjfb8856606 	return 0;
993d30ea906Sjfb8856606 }
994d30ea906Sjfb8856606 
995d30ea906Sjfb8856606 static inline bool
check_matching_capabilities(uint64_t mask,uint64_t required_mask)996d30ea906Sjfb8856606 check_matching_capabilities(uint64_t mask, uint64_t required_mask)
997d30ea906Sjfb8856606 {
998d30ea906Sjfb8856606 	return (mask & required_mask) == required_mask;
999d30ea906Sjfb8856606 }
1000d30ea906Sjfb8856606 
1001d30ea906Sjfb8856606 static void
enable_bbdev(struct app_config_params * app_params)1002d30ea906Sjfb8856606 enable_bbdev(struct app_config_params *app_params)
1003d30ea906Sjfb8856606 {
1004d30ea906Sjfb8856606 	struct rte_bbdev_info dev_info;
1005d30ea906Sjfb8856606 	const struct rte_bbdev_op_cap *op_cap;
1006d30ea906Sjfb8856606 	uint16_t bbdev_id = app_params->bbdev_id;
1007d30ea906Sjfb8856606 	bool encoder_capable = false;
1008d30ea906Sjfb8856606 	bool decoder_capable = false;
1009d30ea906Sjfb8856606 
1010d30ea906Sjfb8856606 	rte_bbdev_info_get(bbdev_id, &dev_info);
1011d30ea906Sjfb8856606 	op_cap = dev_info.drv.capabilities;
1012d30ea906Sjfb8856606 
1013d30ea906Sjfb8856606 	while (op_cap->type != RTE_BBDEV_OP_NONE) {
1014d30ea906Sjfb8856606 		if (op_cap->type == RTE_BBDEV_OP_TURBO_ENC) {
1015d30ea906Sjfb8856606 			if (check_matching_capabilities(
1016d30ea906Sjfb8856606 					op_cap->cap.turbo_enc.capability_flags,
1017d30ea906Sjfb8856606 					def_op_enc.op_flags))
1018d30ea906Sjfb8856606 				encoder_capable = true;
1019d30ea906Sjfb8856606 		}
1020d30ea906Sjfb8856606 
1021d30ea906Sjfb8856606 		if (op_cap->type == RTE_BBDEV_OP_TURBO_DEC) {
1022d30ea906Sjfb8856606 			if (check_matching_capabilities(
1023d30ea906Sjfb8856606 					op_cap->cap.turbo_dec.capability_flags,
1024d30ea906Sjfb8856606 					def_op_dec.op_flags))
1025d30ea906Sjfb8856606 				decoder_capable = true;
1026d30ea906Sjfb8856606 		}
1027d30ea906Sjfb8856606 
1028d30ea906Sjfb8856606 		op_cap++;
1029d30ea906Sjfb8856606 	}
1030d30ea906Sjfb8856606 
1031d30ea906Sjfb8856606 	if (encoder_capable == false)
1032d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
1033d30ea906Sjfb8856606 			"The specified BBDev %u doesn't have required encoder capabilities!\n",
1034d30ea906Sjfb8856606 			bbdev_id);
1035d30ea906Sjfb8856606 	if (decoder_capable == false)
1036d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
1037d30ea906Sjfb8856606 			"The specified BBDev %u doesn't have required decoder capabilities!\n",
1038d30ea906Sjfb8856606 			bbdev_id);
1039d30ea906Sjfb8856606 
1040d30ea906Sjfb8856606 	prepare_bbdev_device(bbdev_id, &dev_info, app_params);
1041d30ea906Sjfb8856606 }
1042d30ea906Sjfb8856606 
1043d30ea906Sjfb8856606 int
main(int argc,char ** argv)1044d30ea906Sjfb8856606 main(int argc, char **argv)
1045d30ea906Sjfb8856606 {
1046d30ea906Sjfb8856606 	int ret;
1047d30ea906Sjfb8856606 	unsigned int nb_bbdevs, flags, lcore_id;
1048d30ea906Sjfb8856606 	void *sigret;
1049d30ea906Sjfb8856606 	struct app_config_params app_params = def_app_config;
1050d30ea906Sjfb8856606 	struct rte_mempool *ethdev_mbuf_mempool, *bbdev_mbuf_mempool;
1051d30ea906Sjfb8856606 	struct rte_mempool *bbdev_op_pools[RTE_BBDEV_OP_TYPE_COUNT];
1052d30ea906Sjfb8856606 	struct lcore_conf lcore_conf[RTE_MAX_LCORE] = { {0} };
1053d30ea906Sjfb8856606 	struct lcore_statistics lcore_stats[RTE_MAX_LCORE] = { {0} };
1054d30ea906Sjfb8856606 	struct stats_lcore_params stats_lcore;
1055d30ea906Sjfb8856606 	struct rte_ring *enc_to_dec_ring;
1056d30ea906Sjfb8856606 	bool stats_thread_started = false;
1057*2d9fd380Sjfb8856606 	unsigned int main_lcore_id = rte_get_main_lcore();
1058*2d9fd380Sjfb8856606 
1059*2d9fd380Sjfb8856606 	static const struct rte_mbuf_dynfield input_dynfield_desc = {
1060*2d9fd380Sjfb8856606 		.name = "example_bbdev_dynfield_input",
1061*2d9fd380Sjfb8856606 		.size = sizeof(struct rte_mbuf *),
1062*2d9fd380Sjfb8856606 		.align = __alignof__(struct rte_mbuf *),
1063*2d9fd380Sjfb8856606 	};
1064d30ea906Sjfb8856606 
1065d30ea906Sjfb8856606 	rte_atomic16_init(&global_exit_flag);
1066d30ea906Sjfb8856606 
1067d30ea906Sjfb8856606 	sigret = signal(SIGTERM, signal_handler);
1068d30ea906Sjfb8856606 	if (sigret == SIG_ERR)
1069d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "signal(%d, ...) failed", SIGTERM);
1070d30ea906Sjfb8856606 
1071d30ea906Sjfb8856606 	sigret = signal(SIGINT, signal_handler);
1072d30ea906Sjfb8856606 	if (sigret == SIG_ERR)
1073d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "signal(%d, ...) failed", SIGINT);
1074d30ea906Sjfb8856606 
1075d30ea906Sjfb8856606 	ret = rte_eal_init(argc, argv);
1076d30ea906Sjfb8856606 	if (ret < 0)
1077d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
1078d30ea906Sjfb8856606 
1079d30ea906Sjfb8856606 	argc -= ret;
1080d30ea906Sjfb8856606 	argv += ret;
1081d30ea906Sjfb8856606 
1082d30ea906Sjfb8856606 	/* parse application arguments (after the EAL ones) */
1083d30ea906Sjfb8856606 	ret = bbdev_parse_args(argc, argv, &app_params);
1084d30ea906Sjfb8856606 	if (ret < 0)
1085d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "Invalid BBDEV arguments\n");
1086d30ea906Sjfb8856606 
1087d30ea906Sjfb8856606 	/*create bbdev op pools*/
1088d30ea906Sjfb8856606 	bbdev_op_pools[RTE_BBDEV_OP_TURBO_DEC] =
1089d30ea906Sjfb8856606 			rte_bbdev_op_pool_create("bbdev_op_pool_dec",
1090d30ea906Sjfb8856606 			RTE_BBDEV_OP_TURBO_DEC, NB_MBUF, 128, rte_socket_id());
1091d30ea906Sjfb8856606 	bbdev_op_pools[RTE_BBDEV_OP_TURBO_ENC] =
1092d30ea906Sjfb8856606 			rte_bbdev_op_pool_create("bbdev_op_pool_enc",
1093d30ea906Sjfb8856606 			RTE_BBDEV_OP_TURBO_ENC, NB_MBUF, 128, rte_socket_id());
1094d30ea906Sjfb8856606 
1095d30ea906Sjfb8856606 	if ((bbdev_op_pools[RTE_BBDEV_OP_TURBO_DEC] == NULL) ||
1096d30ea906Sjfb8856606 			(bbdev_op_pools[RTE_BBDEV_OP_TURBO_ENC] == NULL))
1097d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "Cannot create bbdev op pools\n");
1098d30ea906Sjfb8856606 
1099d30ea906Sjfb8856606 	/* Create encoder to decoder ring */
1100d30ea906Sjfb8856606 	flags = (app_params.num_enc_cores == 1) ? RING_F_SP_ENQ : 0;
1101d30ea906Sjfb8856606 	if (app_params.num_dec_cores == 1)
1102d30ea906Sjfb8856606 		flags |= RING_F_SC_DEQ;
1103d30ea906Sjfb8856606 
1104d30ea906Sjfb8856606 	enc_to_dec_ring = rte_ring_create("enc_to_dec_ring",
1105d30ea906Sjfb8856606 		rte_align32pow2(NB_MBUF), rte_socket_id(), flags);
1106d30ea906Sjfb8856606 
1107d30ea906Sjfb8856606 	/* Get the number of available bbdev devices */
1108d30ea906Sjfb8856606 	nb_bbdevs = rte_bbdev_count();
1109d30ea906Sjfb8856606 	if (nb_bbdevs <= app_params.bbdev_id)
1110d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
1111d30ea906Sjfb8856606 				"%u BBDevs detected, cannot use BBDev with ID %u!\n",
1112d30ea906Sjfb8856606 				nb_bbdevs, app_params.bbdev_id);
1113d30ea906Sjfb8856606 	printf("Number of bbdevs detected: %d\n", nb_bbdevs);
1114d30ea906Sjfb8856606 
1115d30ea906Sjfb8856606 	if (!rte_eth_dev_is_valid_port(app_params.port_id))
1116d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
1117d30ea906Sjfb8856606 				"cannot use port with ID %u!\n",
1118d30ea906Sjfb8856606 				app_params.port_id);
1119d30ea906Sjfb8856606 
1120d30ea906Sjfb8856606 	/* create the mbuf mempool for ethdev pkts */
1121d30ea906Sjfb8856606 	ethdev_mbuf_mempool = rte_pktmbuf_pool_create("ethdev_mbuf_pool",
1122d30ea906Sjfb8856606 			NB_MBUF, MEMPOOL_CACHE_SIZE, 0,
1123d30ea906Sjfb8856606 			RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
1124d30ea906Sjfb8856606 	if (ethdev_mbuf_mempool == NULL)
1125d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "Cannot create ethdev mbuf mempool\n");
1126d30ea906Sjfb8856606 
1127d30ea906Sjfb8856606 	/* create the mbuf mempool for encoder output */
1128d30ea906Sjfb8856606 	bbdev_mbuf_mempool = rte_pktmbuf_pool_create("bbdev_mbuf_pool",
1129d30ea906Sjfb8856606 			NB_MBUF, MEMPOOL_CACHE_SIZE, 0,
1130d30ea906Sjfb8856606 			RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
1131d30ea906Sjfb8856606 	if (bbdev_mbuf_mempool == NULL)
1132d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "Cannot create ethdev mbuf mempool\n");
1133d30ea906Sjfb8856606 
1134*2d9fd380Sjfb8856606 	/* register mbuf field to store input pointer */
1135*2d9fd380Sjfb8856606 	input_dynfield_offset =
1136*2d9fd380Sjfb8856606 		rte_mbuf_dynfield_register(&input_dynfield_desc);
1137*2d9fd380Sjfb8856606 	if (input_dynfield_offset < 0)
1138*2d9fd380Sjfb8856606 		rte_exit(EXIT_FAILURE, "Cannot register mbuf field\n");
1139*2d9fd380Sjfb8856606 
1140d30ea906Sjfb8856606 	/* initialize ports */
1141d30ea906Sjfb8856606 	ret = initialize_ports(&app_params, ethdev_mbuf_mempool);
1142d30ea906Sjfb8856606 
1143d30ea906Sjfb8856606 	/* Check if all requested lcores are available */
1144d30ea906Sjfb8856606 	for (lcore_id = 0; lcore_id < 8 * sizeof(uint64_t); ++lcore_id)
1145d30ea906Sjfb8856606 		if (((1ULL << lcore_id) & app_params.enc_core_mask) ||
1146d30ea906Sjfb8856606 				((1ULL << lcore_id) & app_params.dec_core_mask))
1147d30ea906Sjfb8856606 			if (!rte_lcore_is_enabled(lcore_id))
1148d30ea906Sjfb8856606 				rte_exit(EXIT_FAILURE,
1149d30ea906Sjfb8856606 						"Requested lcore_id %u is not enabled!\n",
1150d30ea906Sjfb8856606 						lcore_id);
1151d30ea906Sjfb8856606 
1152d30ea906Sjfb8856606 	/* Start ethernet port */
1153d30ea906Sjfb8856606 	ret = rte_eth_dev_start(app_params.port_id);
1154d30ea906Sjfb8856606 	if (ret < 0)
1155d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n",
1156d30ea906Sjfb8856606 				ret, app_params.port_id);
1157d30ea906Sjfb8856606 
1158d30ea906Sjfb8856606 	ret = check_port_link_status(app_params.port_id);
1159d30ea906Sjfb8856606 	if (ret < 0)
1160d30ea906Sjfb8856606 		exit(EXIT_FAILURE);
1161d30ea906Sjfb8856606 
1162d30ea906Sjfb8856606 	/* start BBDevice and save BBDev queue IDs */
1163d30ea906Sjfb8856606 	enable_bbdev(&app_params);
1164d30ea906Sjfb8856606 
1165d30ea906Sjfb8856606 	/* Initialize the port/queue configuration of each logical core */
1166d30ea906Sjfb8856606 	lcore_conf_init(&app_params, lcore_conf, bbdev_op_pools,
1167d30ea906Sjfb8856606 			bbdev_mbuf_mempool, enc_to_dec_ring, lcore_stats);
1168d30ea906Sjfb8856606 
1169d30ea906Sjfb8856606 	stats_lcore.app_params = &app_params;
1170d30ea906Sjfb8856606 	stats_lcore.lconf = lcore_conf;
1171d30ea906Sjfb8856606 
1172*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
1173d30ea906Sjfb8856606 		if (lcore_conf[lcore_id].core_type != 0)
1174*2d9fd380Sjfb8856606 			/* launch per-lcore processing loop on worker lcores */
1175d30ea906Sjfb8856606 			rte_eal_remote_launch(processing_loop,
1176d30ea906Sjfb8856606 					&lcore_conf[lcore_id], lcore_id);
1177d30ea906Sjfb8856606 		else if (!stats_thread_started) {
1178d30ea906Sjfb8856606 			/* launch statistics printing loop */
1179d30ea906Sjfb8856606 			rte_eal_remote_launch(stats_loop, &stats_lcore,
1180d30ea906Sjfb8856606 					lcore_id);
1181d30ea906Sjfb8856606 			stats_thread_started = true;
1182d30ea906Sjfb8856606 		}
1183d30ea906Sjfb8856606 	}
1184d30ea906Sjfb8856606 
1185d30ea906Sjfb8856606 	if (!stats_thread_started &&
1186*2d9fd380Sjfb8856606 			lcore_conf[main_lcore_id].core_type != 0)
1187d30ea906Sjfb8856606 		rte_exit(EXIT_FAILURE,
1188d30ea906Sjfb8856606 				"Not enough lcores to run the statistics printing loop!");
1189*2d9fd380Sjfb8856606 	else if (lcore_conf[main_lcore_id].core_type != 0)
1190*2d9fd380Sjfb8856606 		processing_loop(&lcore_conf[main_lcore_id]);
1191d30ea906Sjfb8856606 	else if (!stats_thread_started)
1192d30ea906Sjfb8856606 		stats_loop(&stats_lcore);
1193d30ea906Sjfb8856606 
1194*2d9fd380Sjfb8856606 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
1195d30ea906Sjfb8856606 		ret |= rte_eal_wait_lcore(lcore_id);
1196d30ea906Sjfb8856606 	}
1197d30ea906Sjfb8856606 
1198d30ea906Sjfb8856606 	return ret;
1199d30ea906Sjfb8856606 }
1200