All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amr Mokhtar <amr.mokhtar@intel.com>
To: dev@dpdk.org
Cc: niall.power@intel.com, chris.macnamara@intel.com,
	Amr Mokhtar <amr.mokhtar@intel.com>
Subject: [PATCH v1 4/6] bbdev: sample app
Date: Sat, 30 Sep 2017 02:37:53 +0100	[thread overview]
Message-ID: <1506735475-77078-4-git-send-email-amr.mokhtar@intel.com> (raw)
In-Reply-To: <1506735475-77078-1-git-send-email-amr.mokhtar@intel.com>

Signed-off-by: Amr Mokhtar <amr.mokhtar@intel.com>
---
 examples/Makefile           |    1 +
 examples/bbdev_app/Makefile |   50 ++
 examples/bbdev_app/main.c   | 1260 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1311 insertions(+)
 create mode 100644 examples/bbdev_app/Makefile
 create mode 100644 examples/bbdev_app/main.c

diff --git a/examples/Makefile b/examples/Makefile
index 28354ff..976deb3 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -101,5 +101,6 @@ endif
 endif
 
 DIRS-y += eventdev_pipeline_sw_pmd
+DIRS-$(CONFIG_RTE_LIBRTE_BBDEV) += bbdev_app
 
 include $(RTE_SDK)/mk/rte.extsubdir.mk
diff --git a/examples/bbdev_app/Makefile b/examples/bbdev_app/Makefile
new file mode 100644
index 0000000..1583251
--- /dev/null
+++ b/examples/bbdev_app/Makefile
@@ -0,0 +1,50 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2017 Intel Corporation. All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= x86_64-native-linuxapp-gcc
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# binary name
+APP = bbdev
+
+# all source are stored in SRCS-y
+SRCS-y := main.c
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+include $(RTE_SDK)/mk/rte.extapp.mk
diff --git a/examples/bbdev_app/main.c b/examples/bbdev_app/main.c
new file mode 100644
index 0000000..cf656d5
--- /dev/null
+++ b/examples/bbdev_app/main.c
@@ -0,0 +1,1260 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/unistd.h>
+#include <sys/queue.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <assert.h>
+#include <getopt.h>
+#include <signal.h>
+#include <inttypes.h>
+
+#include "rte_common.h"
+#include "rte_eal.h"
+#include "rte_cycles.h"
+#include "rte_eal.h"
+#include "rte_ether.h"
+#include "rte_ethdev.h"
+#include "rte_ip.h"
+#include "rte_lcore.h"
+#include "rte_malloc.h"
+#include "rte_mbuf.h"
+#include "rte_memory.h"
+#include "rte_mempool.h"
+#include "rte_log.h"
+#include "rte_bbdev.h"
+#include "rte_bbdev_op.h"
+
+#define MAX_PKT_BURST 32
+#define NB_MBUF 8163
+#define MAX_RX_QUEUE_PER_LCORE 16
+#define MAX_TX_QUEUE_PER_LCORE 16
+#define MEMPOOL_CACHE_SIZE 256
+
+/*Configurable number of RX/TX ring descriptors */
+#define RTE_TEST_RX_DESC_DEFAULT 128
+#define RTE_TEST_TX_DESC_DEFAULT 512
+
+#define BBDEV_ASSERT(a) do { \
+	if (!(a)) { \
+		usage(prgname); \
+		return -1; \
+	} \
+} while (0)
+
+static struct rte_mempool *ethdev_mbuf_mempool;
+
+struct dev_qs {
+	unsigned int port_id;
+	unsigned int queues_list[RTE_MAX_QUEUES_PER_PORT];
+	unsigned int queues;
+};
+
+static struct rte_mempool *bbdev_op_pool[RTE_BBDEV_OP_TYPE_COUNT];
+
+/**all lcores used*/
+struct lcore_setup {
+	unsigned int rxte_lcores;
+	unsigned int rxte_lcore_list[RTE_MAX_LCORE];
+	unsigned int tetx_lcores;
+	unsigned int tetx_lcore_list[RTE_MAX_LCORE];
+	unsigned int rxtd_lcores;
+	unsigned int rxtd_lcore_list[RTE_MAX_LCORE];
+	unsigned int tdtx_lcores;
+	unsigned int tdtx_lcore_list[RTE_MAX_LCORE];
+};
+
+/** each lcore configuration */
+struct lcore_queue_conf {
+	unsigned int nb_ports;
+	struct dev_qs port_list[RTE_MAX_ETHPORTS];
+	/* ethernet addresses of ports */
+	struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
+
+	unsigned int bbdev_id;
+
+	unsigned int bbdev_qs[128];
+	unsigned int nb_bbdev_qs;
+
+	struct rte_mempool *mbuf_pool;
+} __rte_cache_aligned;
+
+static struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
+
+static const struct rte_eth_conf port_conf = {
+	.rxmode = {
+		.mq_mode = ETH_MQ_RX_NONE,
+		.max_rx_pkt_len = ETHER_MAX_LEN,
+		.split_hdr_size = 0,
+		.header_split = 0, /**< Header Split disabled */
+		.hw_ip_checksum = 0, /**< IP checksum offload disabled */
+		.hw_vlan_filter = 0, /**< VLAN filtering disabled */
+		.jumbo_frame = 0, /**< Jumbo Frame Support disabled */
+		.hw_strip_crc = 0, /**< CRC stripped by hardware */
+	},
+	.txmode = {
+		.mq_mode = ETH_MQ_TX_NONE,
+	},
+};
+
+struct rte_bbdev_op_turbo_enc def_op_enc = {
+	.rv_index = 0,
+	.code_block_mode = 1,
+	.cb_params.k = 112,
+	.cb_params.e = 272,
+	.cb_params.ncb = 192,
+	.op_flags = RTE_BBDEV_TURBO_CRC_24B_ATTACH
+};
+
+struct rte_bbdev_op_turbo_dec def_op_dec = {
+	.cb_params.e = 44,
+	.cb_params.k = 112,
+	.rv_index = 0,
+	.iter_max = 8,
+	.iter_min = 4,
+	.ext_scale = 15,
+	.num_maps = 0,
+	.op_flags = RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE |
+		RTE_BBDEV_TURBO_EQUALIZER | RTE_BBDEV_TURBO_SOFT_OUTPUT
+};
+
+struct bbdev_config_params {
+	uint8_t downlink_lcores;
+	uint8_t uplink_lcores;
+
+	uint8_t downlink_rx_ports;
+	uint8_t downlink_tx_ports;
+
+	uint8_t uplink_rx_ports;
+	uint8_t uplink_tx_ports;
+
+	unsigned int rx_port_list[MAX_RX_QUEUE_PER_LCORE];
+	unsigned int tx_port_list[MAX_TX_QUEUE_PER_LCORE];
+};
+
+struct lcore_statistics {
+	unsigned int enqueued;
+	unsigned int dequeued;
+	unsigned int lost_packets;
+} __rte_cache_aligned;
+
+static struct lcore_statistics lcore_stats[RTE_MAX_LCORE];
+
+static volatile int global_exit_flag;
+
+struct port_queues {
+	unsigned int nb_rx_qs;
+	unsigned int nb_tx_qs;
+};
+
+static struct port_queues ports_qs[RTE_MAX_ETHPORTS];
+
+/* display usage */
+static inline void
+usage(const char *prgname)
+{
+	printf("%s [EAL options] "
+		"  --\n"
+		"  --downlink_cores - downlink cores mask\n"
+		"  --uplink_cores - uplink cores mask\n"
+		"  --downlink_rx_ports - downlink Rx ports mask\n"
+		"  --downlink_tx_ports - downlink Tx ports mask\n"
+		"  --uplink_tx_ports -uplink Tx ports mask\n"
+		"  --uplink_rx_ports -uplink Rx ports msk\n"
+		"\n", prgname);
+}
+
+/* parse port or core mask */
+static inline
+uint8_t bbdev_parse_mask(const char *mask)
+{
+	char *end = NULL;
+	unsigned long pm;
+
+	/* parse hexadecimal string */
+	pm = strtoul(mask, &end, 16);
+	if ((mask[0] == '\0') || (end == NULL) || (*end != '\0'))
+		return 0;
+
+	if (pm == 0)
+		return 0;
+
+	return pm;
+}
+
+static int
+bbdev_parse_args(int argc, char **argv,
+		struct bbdev_config_params *bbdev_params)
+{
+	int optind = 0;
+	int opt;
+	int opt_indx = 0;
+	char *prgname = argv[0];
+
+	memset(bbdev_params, 0, sizeof(*bbdev_params));
+
+	static struct option lgopts[] = {
+			{ "downlink_cores", required_argument, 0, 'c' },
+			{ "uplink_cores", required_argument, 0, 'C' },
+			{ "downlink_rx_ports", required_argument, 0, 'r' },
+			{ "downlink_tx_ports", required_argument, 0, 't' },
+			{ "uplink_rx_ports", required_argument, 0, 'R' },
+			{ "uplink_tx_ports", required_argument, 0, 'T' },
+			{ NULL, 0, 0, 0 }
+	};
+
+	BBDEV_ASSERT(argc != 0);
+	BBDEV_ASSERT(argv != NULL);
+	BBDEV_ASSERT(bbdev_params != NULL);
+
+	while ((opt = getopt_long(argc, argv, "c:C:r:t:R:T:", lgopts,
+			&opt_indx)) != EOF) {
+
+		switch (opt) {
+		case 'c':
+			bbdev_params->downlink_lcores =
+					bbdev_parse_mask(optarg);
+			if (bbdev_params->downlink_lcores == 0) {
+				usage(prgname);
+				return -1;
+			}
+			break;
+
+		case 'C':
+			bbdev_params->uplink_lcores =
+					bbdev_parse_mask(optarg);
+			if (bbdev_params->uplink_lcores == 0) {
+				usage(prgname);
+				return -1;
+			}
+			break;
+
+		case 'r':
+			bbdev_params->downlink_rx_ports =
+					bbdev_parse_mask(optarg);
+			if (bbdev_params->downlink_rx_ports == 0) {
+				usage(prgname);
+				return -1;
+			}
+			break;
+
+		case 't':
+			bbdev_params->downlink_tx_ports =
+					bbdev_parse_mask(optarg);
+			if (bbdev_params->downlink_tx_ports == 0) {
+				usage(prgname);
+				return -1;
+			}
+			break;
+
+		case 'R':
+			bbdev_params->uplink_rx_ports =
+					bbdev_parse_mask(optarg);
+			if (bbdev_params->uplink_rx_ports == 0) {
+				usage(prgname);
+				return -1;
+			}
+			break;
+
+		case 'T':
+			bbdev_params->uplink_tx_ports =
+					bbdev_parse_mask(optarg);
+			if (bbdev_params->uplink_tx_ports == 0) {
+				usage(prgname);
+				return -1;
+			}
+			break;
+
+		default:
+			usage(prgname);
+			return -1;
+		}
+	}
+	optind = 0;
+	return optind;
+}
+
+static void
+signal_handler(int signum)
+{
+	printf("\nSignal %d received", signum);
+	global_exit_flag = 1;
+}
+
+static void
+print_mac(unsigned int portid, struct ether_addr *bbdev_ports_eth_address)
+{
+	printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
+			(unsigned int) portid,
+			bbdev_ports_eth_address[portid].addr_bytes[0],
+			bbdev_ports_eth_address[portid].addr_bytes[1],
+			bbdev_ports_eth_address[portid].addr_bytes[2],
+			bbdev_ports_eth_address[portid].addr_bytes[3],
+			bbdev_ports_eth_address[portid].addr_bytes[4],
+			bbdev_ports_eth_address[portid].addr_bytes[5]);
+}
+
+/* Check the link status of all ports in up to 9s, and print them finally */
+static void
+check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
+{
+#define CHECK_INTERVAL 100 /* 100ms */
+#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
+	uint8_t portid, count, all_ports_up, print_flag = 0;
+	struct rte_eth_link link;
+
+	printf("\nChecking link status");
+	fflush(stdout);
+
+	for (count = 0; count <= MAX_CHECK_TIME; count++) {
+		all_ports_up = 1;
+		for (portid = 0; portid < port_num; portid++) {
+			if ((port_mask & (1 << portid)) == 0)
+				continue;
+			memset(&link, 0, sizeof(link));
+			rte_eth_link_get_nowait(portid, &link);
+			/* print link status if flag set */
+			if (print_flag == 1) {
+				if (link.link_status) {
+					const char *dp = (link.link_duplex ==
+							ETH_LINK_FULL_DUPLEX) ?
+							"full-duplex" :
+							"half-duplex";
+					printf("Port %u Link Up - speed %u Mbps"
+							" - %s\n", portid,
+							link.link_speed,
+							dp);
+				} else
+					printf("Port %d Link Down\n", portid);
+				continue;
+			}
+			/* clear all_ports_up flag if any link down */
+			if (link.link_status == 0) {
+				all_ports_up = 0;
+				break;
+			}
+		}
+		/* after finally printing all link status, get out */
+		if (print_flag == 1)
+			break;
+
+		if (all_ports_up == 0) {
+			printf(".");
+			fflush(stdout);
+			rte_delay_ms(CHECK_INTERVAL);
+		}
+
+		/* set the print_flag if all ports up or timeout */
+		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
+			print_flag = 1;
+			printf("done\n");
+		}
+	}
+}
+
+static void
+update_pkt_mac(uint16_t n, struct rte_mbuf *pkts_burst[],
+		struct ether_addr *addr, unsigned int dest_portid)
+{
+	struct ether_hdr *eth;
+	void *tmp;
+
+	for (uint16_t i = 0; i < n; i++) {
+		eth = rte_pktmbuf_mtod(pkts_burst[i], struct ether_hdr *);
+		/* 02:00:00:00:00:xx */
+		tmp = &eth->d_addr.addr_bytes[0];
+		*((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dest_portid << 40);
+		/* src addr */
+		ether_addr_copy(addr, &eth->s_addr);
+	}
+}
+
+static int
+initialize_ports(uint8_t ports_mask, char link, char port_type,
+		uint32_t *bbdev_enabled_port_mask)
+{
+	uint8_t portid;
+	unsigned int enabled_portcount = 0, q;
+	int ret;
+	struct port_queues *port_qs;
+	/* ethernet addresses of ports */
+	struct ether_addr bbdev_dl_ports_eth_addr[RTE_MAX_ETHPORTS];
+	struct ether_addr bbdev_ul_ports_eth_addr[RTE_MAX_ETHPORTS];
+
+	uint8_t nb_ports = rte_eth_dev_count();
+	if (nb_ports == 0) {
+		printf("No Ethernet ports available\n");
+		return -1;
+	}
+
+	for (portid = 0; portid < nb_ports; portid++) {
+
+		/* Skip ports that are not enabled */
+		if ((ports_mask & (1 << portid)) == 0)
+			continue;
+
+		port_qs = &ports_qs[portid];
+		/* initialize ports */
+		printf("\nInitializing %cx port %u... ",
+				port_type, (unsigned) portid);
+		fflush(stdout);
+		ret = rte_eth_dev_configure(portid, port_qs->nb_rx_qs,
+				port_qs->nb_tx_qs, &port_conf);
+
+		if (ret < 0) {
+			printf("Cannot configure device: err=%d, port=%u\n",
+					ret, (unsigned) portid);
+			return -1;
+		}
+		fflush(stdout);
+
+		/* initialize one RX or TX queue on each port*/
+		if (port_type == 'R')
+			for (q = 0; q < port_qs->nb_rx_qs; q++)
+				ret = rte_eth_rx_queue_setup(portid, q,
+						RTE_TEST_RX_DESC_DEFAULT,
+						rte_eth_dev_socket_id(portid),
+						NULL, ethdev_mbuf_mempool);
+		else if (port_type == 'T')
+			for (q = 0; q < port_qs->nb_rx_qs; q++)
+				ret = rte_eth_tx_queue_setup(portid, q,
+						RTE_TEST_TX_DESC_DEFAULT,
+						rte_eth_dev_socket_id(portid),
+						NULL);
+
+		if (ret < 0) {
+			printf("%cL rte_eth_%cx_queue_setup:err=%d, port=%u\n",
+					port_type, link, ret,
+					(unsigned int) portid);
+			return -1;
+		}
+
+		rte_eth_promiscuous_enable(portid);
+
+		if (link == 'D') {
+			rte_eth_macaddr_get(portid,
+					&bbdev_dl_ports_eth_addr[portid]);
+			print_mac(portid, bbdev_dl_ports_eth_addr);
+		} else {
+			rte_eth_macaddr_get(portid,
+					&bbdev_ul_ports_eth_addr[portid]);
+			print_mac(portid, bbdev_ul_ports_eth_addr);
+		}
+
+		*bbdev_enabled_port_mask |= (1 << portid);
+		enabled_portcount++;
+	}
+	return enabled_portcount;
+}
+
+static int
+start_ethdev_ports(uint8_t nb_ports, uint32_t bbdev_enabled_port_mask)
+{
+	unsigned int portid;
+	int ret, ports_started = 0;
+
+	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
+
+		if ((bbdev_enabled_port_mask & (uint32_t)(1 << portid)) == 0)
+			continue;
+		ret = rte_eth_dev_start(portid);
+		if (ret < 0) {
+			printf("rte_eth_dev_start:err=%d, port=%u\n", ret,
+					(unsigned int) portid);
+			return -1;
+		}
+
+		ports_started++;
+		if (ports_started == nb_ports)
+			break;
+	}
+	return ports_started;
+}
+
+static int
+lcore_queue_init(uint8_t nb_ports, struct bbdev_config_params *bbdev_params,
+		struct lcore_setup *l_setup)
+{
+	uint16_t port;
+	unsigned int lcore;
+	int lcount, total_count = 0;
+	struct lcore_queue_conf *qconf;
+
+	/*
+	 * for each core in the uplink populate the array of ports (rx or tx).
+	 * core with odd id receives rx ports, core with even id receives all
+	 * tx ports.
+	 */
+	for (lcore = 0, lcount = 0; lcore < sizeof(int) * 8; lcore++) {
+
+		/* get the lcore_id  */
+		if ((bbdev_params->downlink_lcores & (1 << lcore)) == 0)
+			continue;
+
+		lcount++;
+		for (port = 0; port <= nb_ports; port++) {
+			if ((lcount & 1) == 1) {
+				if (port < nb_ports) {
+					/*get the port id*/
+					if ((bbdev_params->downlink_rx_ports &
+							(1 << port)) == 0)
+						continue;
+
+					l_setup->rxte_lcore_list[
+							l_setup->rxte_lcores] =
+							lcore;
+					printf("Lcore %d: DL RX port %d\n",
+							lcore, port);
+				} else {
+					l_setup->rxte_lcores++;
+					continue;
+				}
+
+			} else {
+				if (port < nb_ports) {
+					if ((bbdev_params->downlink_tx_ports &
+							(1 << port)) == 0)
+						continue;
+
+					l_setup->tdtx_lcore_list[
+							l_setup->tdtx_lcores] =
+							lcore;
+					printf("Lcore %d: DL TX port %d\n",
+							lcore, port);
+				} else {
+					l_setup->tdtx_lcores++;
+					continue;
+				}
+			}
+			qconf = &lcore_queue_conf[lcore];
+			qconf->port_list[qconf->nb_ports].queues++;
+			qconf->port_list[qconf->nb_ports].port_id = port;
+			rte_eth_macaddr_get(port,
+					&qconf->ports_eth_addr[qconf->nb_ports]);
+			qconf->nb_ports++;
+		}
+	}
+
+	if (lcount % 2) {
+		printf("\nNumber of DL lcores is not an even number");
+		return -1;
+	}
+
+	total_count += lcount;
+
+	/*
+	 * for each core in the downlink populate the array of ports (rx or tx).
+	 * core with odd id receives rx ports, core with even id receives all
+	 * tx ports
+	 */
+	for (lcore = 0, lcount = 0; lcore < (sizeof(int) * 8); lcore++) {
+		if ((bbdev_params->uplink_lcores & (1 << lcore)) == 0)
+			continue;
+
+		lcount++;
+		for (port = 0; port <= nb_ports; port++) {
+
+			if ((lcount & 1) == 1) {
+				if (port < nb_ports) {
+					if ((bbdev_params->uplink_rx_ports &
+							(1 << port)) == 0)
+						continue;
+
+					l_setup->rxtd_lcore_list[
+							l_setup->rxtd_lcores] =
+							lcore;
+					printf("Lcore %u: UL RX port %u\n",
+							lcore, port);
+				} else {
+					l_setup->rxtd_lcores++;
+					continue;
+				}
+
+			} else {
+				if (port < nb_ports) {
+					if ((bbdev_params->uplink_tx_ports &
+							(1 << port)) == 0)
+						continue;
+
+					l_setup->tetx_lcore_list[
+							l_setup->tetx_lcores] =
+							lcore;
+					printf("Lcore %d: UL TX port %d\n",
+							lcore, port);
+				} else {
+					l_setup->tetx_lcores++;
+					continue;
+				}
+			}
+			qconf = &lcore_queue_conf[lcore];
+			qconf->port_list[qconf->nb_ports].queues++;
+			qconf->port_list[qconf->nb_ports].port_id = port;
+			rte_eth_macaddr_get(port,
+					&qconf->ports_eth_addr[qconf->nb_ports]);
+			qconf->nb_ports++;
+		}
+	}
+	if (lcount % 2) {
+		printf("\nNumber of DL lcores is not an even number");
+		return -1;
+	}
+	total_count += lcount;
+	/*return number of lcores processed*/
+	return total_count;
+}
+
+static void
+bbdev_dequeue(enum rte_bbdev_op_type op_type)
+{
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	struct rte_bbdev_op *ops_burst[MAX_PKT_BURST];
+	unsigned int i, j, portid, nb_tx, lcoreid, qid = 0, q, nb_tx_sent = 0;
+	struct lcore_queue_conf *qconf;
+	struct lcore_statistics *lcore_stat;
+
+	lcoreid = rte_lcore_id();
+	lcore_stat = &lcore_stats[lcoreid];
+	qconf = &lcore_queue_conf[lcoreid];
+
+	if (qconf->nb_ports == 0)
+		return;
+
+	while (!global_exit_flag) {
+		for (i = 0; i < qconf->nb_ports; i++) {
+			portid = qconf->port_list[i].port_id;
+
+			for (q = 0; q < qconf->port_list[i].queues; q++) {
+				qid = qconf->port_list[i].queues_list[q];
+				/* Dequeue packets from bbdev device*/
+				nb_tx = rte_bbdev_dequeue_ops(qconf->bbdev_id,
+						qconf->bbdev_qs[q], ops_burst,
+						MAX_PKT_BURST);
+
+				if (!nb_tx)
+					continue;
+
+				lcore_stat->dequeued += nb_tx;
+
+				switch (op_type) {
+				case RTE_BBDEV_OP_TURBO_ENC:
+					for (j = 0; j < nb_tx; j++) {
+						pkts_burst[j] =
+							ops_burst[j]->turbo_enc->output.data;
+						/* input mbufs are no longer needed, release! */
+						rte_pktmbuf_free(ops_burst[j]->turbo_enc->input.data);
+					}
+					break;
+
+				case RTE_BBDEV_OP_TURBO_DEC:
+					for (j = 0; j < nb_tx; j++) {
+						pkts_burst[j] =
+							ops_burst[j]->turbo_dec->hard_output.data;
+						/* input mbufs are no longer needed, release! */
+						rte_pktmbuf_free(ops_burst[j]->turbo_dec->input.data);
+					}
+					break;
+
+				default:
+					break;
+				}
+
+				rte_bbdev_op_free_bulk(ops_burst, nb_tx);
+
+				update_pkt_mac(nb_tx, pkts_burst,
+						&(qconf->ports_eth_addr[portid]),
+						portid);
+
+				/*Enqueue packets to ethdev*/
+				nb_tx_sent = rte_eth_tx_burst(
+						(uint8_t)portid, qid,
+						pkts_burst, nb_tx);
+				if (unlikely(nb_tx_sent < nb_tx)) {
+					lcore_stat->lost_packets +=
+							nb_tx - nb_tx_sent;
+					for (j = nb_tx_sent; j < nb_tx; j++)
+						rte_pktmbuf_free(pkts_burst[j]);
+				}
+			}
+		}
+	}
+}
+
+static void
+bbdev_enqueue(enum rte_bbdev_op_type op_type)
+{
+	unsigned int i, portid, nb_rx = 0, j, lcoreid, q, qid = 0;
+	int ret;
+	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
+	struct rte_mbuf *bbdev_pkts[MAX_PKT_BURST];
+	struct rte_bbdev_op *ops_burst[MAX_PKT_BURST];
+	struct lcore_statistics *lcore_stat;
+	struct lcore_queue_conf *qconf = &lcore_queue_conf[rte_lcore_id()];
+
+	if (qconf->nb_ports == 0)
+		return;
+
+	lcoreid = rte_lcore_id();
+	lcore_stat = &lcore_stats[lcoreid];
+
+	/* Read packet from RX queues*/
+	while (!global_exit_flag) {
+
+		for (i = 0; i < qconf->nb_ports; i++) {
+			portid = qconf->port_list[i].port_id;
+
+			for (q = 0; q < qconf->port_list[i].queues; q++) {
+
+				qid = qconf->port_list[i].queues_list[q];
+				/* Dequeue packets from ethdev */
+				nb_rx = rte_eth_rx_burst((uint8_t) portid, qid,
+						pkts_burst, MAX_PKT_BURST);
+
+				if (!nb_rx)
+					continue;
+
+				if (rte_bbdev_op_alloc_bulk(bbdev_op_pool[op_type],
+						op_type, ops_burst, nb_rx) != 0)
+					continue;
+
+				ret = rte_pktmbuf_alloc_bulk(qconf->mbuf_pool, bbdev_pkts,
+						MAX_PKT_BURST);
+				if (ret < 0)
+					continue;
+
+				switch (op_type) {
+				case RTE_BBDEV_OP_TURBO_ENC:
+					for (j = 0; j < nb_rx; j++) {
+						/* append the size of the ethernet header */
+						rte_pktmbuf_append(bbdev_pkts[j],
+								sizeof(struct ether_hdr));
+						/* copy the ethernet header */
+						void *in_buf = rte_pktmbuf_mtod(pkts_burst[j],
+								void *);
+						void *out_buf = rte_pktmbuf_mtod(bbdev_pkts[j],
+								void *);
+						rte_memcpy(out_buf, in_buf,
+								sizeof(struct ether_hdr));
+						/* set op */
+						ops_burst[j]->type = RTE_BBDEV_OP_TURBO_ENC;
+						*(ops_burst[j]->turbo_enc) = def_op_enc;
+						ops_burst[j]->turbo_enc->input.offset =
+								sizeof(struct ether_hdr);
+						ops_burst[j]->turbo_enc->input.length =
+								rte_pktmbuf_pkt_len(bbdev_pkts[j]);
+						ops_burst[j]->turbo_enc->input.data =
+								pkts_burst[j];
+						ops_burst[j]->turbo_enc->output.offset =
+								sizeof(struct ether_hdr);
+						ops_burst[j]->turbo_enc->output.data =
+								bbdev_pkts[j];
+					}
+					break;
+
+				case RTE_BBDEV_OP_TURBO_DEC:
+					for (j = 0; j < nb_rx; j++) {
+						/* append the size of the ethernet header */
+						rte_pktmbuf_append(bbdev_pkts[j],
+							sizeof(struct ether_hdr));
+						/* copy the ethernet header */
+						void *in_buf = rte_pktmbuf_mtod(pkts_burst[j],
+								void *);
+						void *out_buf = rte_pktmbuf_mtod(bbdev_pkts[j],
+								void *);
+						rte_memcpy(out_buf, in_buf,
+								sizeof(struct ether_hdr));
+						/* set op */
+						ops_burst[j]->type = RTE_BBDEV_OP_TURBO_DEC;
+						*(ops_burst[j]->turbo_dec) = def_op_dec;
+						ops_burst[j]->turbo_dec->input.offset =
+								sizeof(struct ether_hdr);
+						ops_burst[j]->turbo_dec->input.length =
+								rte_pktmbuf_pkt_len(bbdev_pkts[j]);
+						ops_burst[j]->turbo_dec->input.data =
+								pkts_burst[j];
+						ops_burst[j]->turbo_enc->output.offset =
+								sizeof(struct ether_hdr);
+						ops_burst[j]->turbo_dec->hard_output.data =
+								bbdev_pkts[j];
+					}
+					break;
+
+				default:
+					break;
+				}
+				/* Enqueue packets on BBDEV device */
+				nb_rx = rte_bbdev_enqueue_ops(qconf->bbdev_id,
+						qconf->bbdev_qs[q], ops_burst,
+						nb_rx);
+				lcore_stat->enqueued += nb_rx;
+			}
+		}
+	}
+}
+
+static void
+print_lcore_stats(unsigned lcore_id)
+{
+	struct lcore_statistics *lcore_stat;
+	static const char *stats_border = "_______";
+
+	lcore_stat = &lcore_stats[lcore_id];
+	printf("\nLcore %d: %s enqueued count:\t\t%u\n",
+			lcore_id, stats_border, lcore_stat->enqueued);
+	printf("Lcore %d: %s dequeued count:\t\t%u\n",
+			lcore_id, stats_border, lcore_stat->dequeued);
+}
+
+static void
+print_stats(struct lcore_setup *lcore_setup)
+{
+	unsigned l_id;
+	int x, nb_ports, dev_id, len, ret, i;
+
+	struct rte_eth_xstat *xstats;
+	struct rte_eth_xstat_name *xstats_names;
+	struct rte_bbdev_stats bbstats;
+	static const char *stats_border = "_______";
+
+	const char clr[] = { 27, '[', '2', 'J', '\0' };
+	const char topLeft[] = { 27, '[', '1', ';', '1', 'H', '\0' };
+
+	/* Clear screen and move to top left */
+	printf("%s%s", clr, topLeft);
+
+	nb_ports = rte_eth_dev_count();
+	printf("PORT STATISTICS:\n================\n");
+	for (x = 0; x < nb_ports; x++) {
+
+		len = rte_eth_xstats_get(x, NULL, 0);
+		if (len < 0)
+			rte_exit(EXIT_FAILURE,
+					"rte_eth_xstats_get(%hhu) failed: %d",
+					x, len);
+
+		xstats = calloc(len, sizeof(*xstats));
+		if (xstats == NULL)
+			rte_exit(EXIT_FAILURE,
+					"Failed to calloc memory for xstats");
+
+		ret = rte_eth_xstats_get(x, xstats, len);
+		if (ret < 0 || ret > len)
+			rte_exit(EXIT_FAILURE,
+					"rte_eth_xstats_get(%hhu) len%i failed: %d",
+					x, len, ret);
+
+		xstats_names = calloc(len, sizeof(*xstats_names));
+		if (xstats_names == NULL)
+			rte_exit(EXIT_FAILURE,
+					"Failed to calloc memory for xstats_names");
+
+		ret = rte_eth_xstats_get_names(x, xstats_names, len);
+		if (ret < 0 || ret > len)
+			rte_exit(EXIT_FAILURE,
+					"rte_eth_xstats_get_names(%hhu) len%i failed: %d",
+					x, len, ret);
+
+		for (i = 0; i < len; i++) {
+			if (xstats[i].value > 0)
+				printf("Port %u: %s %s:\t\t%"PRIu64"\n",
+						x, stats_border,
+						xstats_names[i].name,
+						xstats[i].value);
+		}
+	}
+
+	printf("\nBBDEV STATISTICS:\n=================\n");
+	RTE_BBDEV_FOREACH(dev_id) {
+		rte_bbdev_stats_get((uint8_t) dev_id, &bbstats);
+		printf("BBDEV %u: %s enqueue count:\t\t%"PRIu64"\n",
+				dev_id, stats_border,
+				bbstats.enqueued_count);
+		printf("BBDEV %u: %s dequeue count:\t\t%"PRIu64"\n",
+				dev_id, stats_border,
+				bbstats.dequeued_count);
+		printf("BBDEV %u: %s enqueue error count:\t\t%"PRIu64"\n",
+				dev_id, stats_border,
+				bbstats.enqueue_err_count);
+		printf("BBDEV %u: %s dequeue error count:\t\t%"PRIu64"\n\n",
+				dev_id, stats_border,
+				bbstats.dequeue_err_count);
+	}
+
+	printf("LCORE STATISTICS:\n=================\n");
+	for (l_id = 0; l_id < lcore_setup->tdtx_lcores; l_id++)
+		print_lcore_stats(lcore_setup->tdtx_lcore_list[l_id]);
+	for (l_id = 0; l_id < lcore_setup->tetx_lcores; l_id++)
+		print_lcore_stats(lcore_setup->tetx_lcore_list[l_id]);
+	for (l_id = 0; l_id < lcore_setup->rxtd_lcores; l_id++)
+		print_lcore_stats(lcore_setup->rxtd_lcore_list[l_id]);
+	for (l_id = 0; l_id < lcore_setup->rxte_lcores; l_id++)
+		print_lcore_stats(lcore_setup->rxte_lcore_list[l_id]);
+}
+
+static void
+qs_to_lcores(unsigned int nb_lcores, unsigned int lcores[])
+{
+	unsigned int port = 0, l = 0, lcore, y, x, queue, nb_ports = 0, q_id;
+	struct lcore_queue_conf *qconf;
+	struct dev_qs temp[RTE_MAX_LCORE];
+	int count = 0;
+	struct dev_qs *p;
+	struct port_queues *port_qs;
+
+	/*
+	 * for each core copy array of ports (holding all ports available to
+	 * this lcore) from qconf into temp array and empty the one in qconf
+	 */
+	for (x = 0; x < nb_lcores; x++) {
+
+		lcore = lcores[x];
+		qconf = &lcore_queue_conf[lcore];
+		nb_ports = qconf->nb_ports;
+		qconf->nb_ports = 0;
+		p = qconf->port_list;
+
+		for (y = 0; y < nb_ports; y++, p++) {
+			temp[y] = *p;
+			p->port_id = 0;
+		}
+	}
+	/*
+	 * re-populate array of ports and queues in qconf according to number
+	 * of available lcores, ports, and queues so only the required ports
+	 * and queues stay in the configuration of each particular lcore
+	 */
+	while (port < nb_ports || l < nb_lcores) {
+
+		if (port < nb_ports && l == nb_lcores) {
+			l = 0;
+			count++;
+		}
+		if (port == nb_ports && l < nb_lcores)
+			port = 0;
+
+		lcore = lcores[l];
+		qconf = &lcore_queue_conf[lcore];
+		port_qs = &ports_qs[temp[port].port_id];
+
+		if ((lcore & 1) == 1) {
+			qconf->port_list[count].port_id =
+					temp[port].port_id;
+
+			for (q_id = 0; q_id < qconf->port_list[count].queues;
+					q_id++) {
+				qconf->port_list[count].queues_list[q_id] =
+						port_qs->nb_tx_qs;
+				port_qs->nb_tx_qs++;
+			}
+
+			qconf->nb_ports++;
+			queue++;
+		} else {
+			qconf->port_list[count].port_id =
+					temp[port].port_id;
+			for (q_id = 0; q_id < qconf->port_list[count].queues;
+					q_id++) {
+				qconf->port_list[count].queues_list[q_id] =
+						port_qs->nb_rx_qs;
+				port_qs->nb_rx_qs++;
+			}
+			qconf->nb_ports++;
+			queue++;
+		}
+		printf("Lcore: %u connected to port: %u\n",
+				lcores[l], temp[port].port_id);
+		port++;
+		l++;
+	}
+}
+
+static void
+main_loop(struct lcore_setup *lcore_setup)
+{
+	unsigned int i = 0, this_lcore;
+	this_lcore = rte_lcore_id();
+
+	/* print stats on master core */
+	if (rte_get_master_lcore() == this_lcore) {
+		while (!global_exit_flag) {
+			print_stats(lcore_setup);
+			rte_delay_ms(500);
+		}
+	}
+
+	for (i = 0; i < lcore_setup->rxte_lcores; i++) {
+		if (lcore_setup->rxte_lcore_list[i] == this_lcore)
+			bbdev_enqueue(RTE_BBDEV_OP_TURBO_ENC);
+	}
+
+	for (i = 0; i < lcore_setup->tetx_lcores; i++) {
+		if (lcore_setup->tetx_lcore_list[i] == this_lcore)
+			bbdev_dequeue(RTE_BBDEV_OP_TURBO_ENC);
+	}
+
+	for (i = 0; i < lcore_setup->rxtd_lcores; i++) {
+		if (lcore_setup->rxtd_lcore_list[i] == this_lcore)
+			bbdev_enqueue(RTE_BBDEV_OP_TURBO_DEC);
+	}
+
+	for (i = 0; i < lcore_setup->tdtx_lcores; i++) {
+		if (lcore_setup->tdtx_lcore_list[i] == this_lcore)
+			bbdev_dequeue(RTE_BBDEV_OP_TURBO_DEC);
+	}
+}
+
+static int
+launch_one_lcore(void *arg)
+{
+	main_loop((struct lcore_setup *)arg);
+	return 0;
+}
+
+static int
+prepare_bbdev_device(unsigned int dev_id, uint8_t qs_nb)
+{
+	int ret;
+	unsigned int q_id;
+	struct rte_bbdev_info info;
+	struct rte_bbdev_queue_conf qconf = {0};
+
+	ret = rte_bbdev_configure(dev_id, qs_nb, NULL);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE,
+				"ERROR(%d): BBDEV %u not configured properly\n",
+				ret, dev_id);
+
+	rte_bbdev_info_get(dev_id, &info);
+
+	/* setup device queues */
+	qconf.socket = info.socket_id;
+	qconf.queue_size = info.drv.queue_size_lim;
+	qconf.op_type = (dev_id & 0x1) ? RTE_BBDEV_OP_TURBO_DEC :
+			RTE_BBDEV_OP_TURBO_ENC;
+
+	for (q_id = 0; q_id < qs_nb; q_id++) {
+
+		ret = rte_bbdev_queue_configure(dev_id, q_id, &qconf);
+		if (ret < 0)
+			rte_exit(EXIT_FAILURE,
+					"ERROR(%d): BBDEV %u queue %u not configured properly\n",
+					ret, dev_id, q_id);
+	}
+
+	ret = rte_bbdev_start(dev_id);
+
+	if (ret != 0)
+		rte_exit(EXIT_FAILURE, "ERROR(%d): BBDEV %u not started\n",
+			ret, dev_id);
+
+	printf("BBdev %u started\n", dev_id);
+
+	return 0;
+}
+
+static void
+enable_bbdev(unsigned int lcores[], unsigned int nb_lcores, unsigned int dev_id)
+{
+	unsigned int i, nb_qs, tot_nb_bbdev_qs = 1, lcore, lcoreid;
+	struct lcore_queue_conf *qconf, *qconf_next;
+	unsigned int nb_bbdev_qs = 0;
+	char pool_name[RTE_MEMPOOL_NAMESIZE];
+
+	/* set num of port queues and bbdev queues for each lcore on the link */
+	for (lcore = 0; lcore < nb_lcores; lcore++) {
+		nb_qs = 0;
+		lcoreid = lcores[lcore];
+		qconf = &lcore_queue_conf[lcoreid];
+
+		for (i = 0; i < qconf->nb_ports; i++)
+			nb_qs += qconf->port_list->queues;
+
+		for (i = 0; i < nb_qs; i++) {
+			qconf->bbdev_qs[i] = nb_bbdev_qs;
+			nb_bbdev_qs++;
+		}
+
+		/* create the mbuf mempool for ethdev pkts */
+		snprintf(pool_name, sizeof(pool_name), "bbdev%d_mbuf_pool%d",
+				dev_id, lcore);
+		qconf->mbuf_pool = rte_pktmbuf_pool_create(pool_name,
+				NB_MBUF, MEMPOOL_CACHE_SIZE, 0,
+				RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+		if (qconf->mbuf_pool == NULL)
+			rte_exit(EXIT_FAILURE,
+					"Unable to create '%s' pool\n", pool_name);
+
+		qconf->nb_bbdev_qs = nb_qs;
+		qconf->bbdev_id = dev_id;
+		printf("BBdev: %u, lcore %u\n", dev_id, lcoreid);
+
+		qconf_next = &lcore_queue_conf[lcoreid + 1];
+		qconf_next->bbdev_id = dev_id;
+
+		for (i = 0; i < nb_qs; i++)
+			qconf_next->bbdev_qs[i] = qconf->bbdev_qs[i];
+
+		qconf_next->nb_bbdev_qs = nb_qs;
+		printf("BBdev: %u, lcore %u\n", dev_id, lcoreid + 1);
+	}
+
+	/* count the number of queues needed on the bbdev device on this link */
+	for (lcore = 0; lcore < nb_lcores; lcore++) {
+		lcoreid = lcores[lcore];
+		qconf = &lcore_queue_conf[lcoreid];
+		tot_nb_bbdev_qs += qconf->nb_bbdev_qs;
+	}
+
+	prepare_bbdev_device(dev_id, tot_nb_bbdev_qs);
+}
+
+int
+main(int argc, char **argv)
+{
+	int ret, nb_bbdevs, nb_ports;
+	int enabled_portcount = 0;
+	uint8_t lcore_id;
+	char rx = 'R', tx = 'T', up_link = 'U', down_link = 'D';
+	void *sigret;
+	uint32_t bbdev_enabled_port_mask = 0;
+	struct lcore_setup lcore_setup = { 0 };
+	struct bbdev_config_params bbdev_params = { 0 };
+
+	sigret = signal(SIGTERM, signal_handler);
+	if (sigret == SIG_ERR)
+		rte_exit(EXIT_FAILURE, "signal(%d, ...) failed", SIGTERM);
+
+	sigret = signal(SIGINT, signal_handler);
+	if (sigret == SIG_ERR)
+		rte_exit(EXIT_FAILURE, "signal(%d, ...) failed", SIGINT);
+
+	ret = rte_eal_init(argc, argv);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
+
+	argc -= ret;
+	argv += ret;
+
+	/* parse application arguments (after the EAL ones) */
+	ret = bbdev_parse_args(argc, argv, &bbdev_params);
+
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Invalid BBDEV arguments\n");
+
+	/* Get number of available bbdev devices */
+	nb_bbdevs = rte_bbdev_count();
+	if (nb_bbdevs == 0)
+		rte_exit(EXIT_FAILURE, "No bbdevs detected!\n");
+	printf("Number of bbdevs detected: %d\n", nb_bbdevs);
+
+	/* Get number of available ethdev devices */
+	nb_ports = rte_eth_dev_count();
+	/* Initialize the port/queue configuration of each logical core */
+	ret = lcore_queue_init(nb_ports, &bbdev_params, &lcore_setup);
+	if (ret < nb_bbdevs * 2)
+		rte_exit(EXIT_FAILURE, "Failed to initialize queues.\n");
+
+	/* reconfigure ports to lcores assignment to allow for multiple lcores
+	 * usage
+	 */
+	qs_to_lcores(lcore_setup.rxte_lcores, lcore_setup.rxte_lcore_list);
+	qs_to_lcores(lcore_setup.rxtd_lcores, lcore_setup.rxtd_lcore_list);
+	qs_to_lcores(lcore_setup.tdtx_lcores, lcore_setup.tdtx_lcore_list);
+	qs_to_lcores(lcore_setup.tetx_lcores, lcore_setup.tetx_lcore_list);
+
+	/* create the mbuf mempool for ethdev pkts */
+	ethdev_mbuf_mempool = rte_pktmbuf_pool_create("ethdev_mbuf_pool",
+			NB_MBUF, MEMPOOL_CACHE_SIZE, 0,
+			RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
+	if (ethdev_mbuf_mempool == NULL)
+		rte_exit(EXIT_FAILURE, "Cannot create ethdev mbuf mempool\n");
+
+	/*initialize ports*/
+	enabled_portcount = initialize_ports(bbdev_params.downlink_rx_ports,
+			down_link, rx, &bbdev_enabled_port_mask);
+	enabled_portcount += initialize_ports(bbdev_params.downlink_tx_ports,
+			down_link, tx, &bbdev_enabled_port_mask);
+	enabled_portcount += initialize_ports(bbdev_params.uplink_rx_ports,
+			up_link, rx, &bbdev_enabled_port_mask);
+	enabled_portcount += initialize_ports(bbdev_params.uplink_tx_ports,
+			up_link, tx, &bbdev_enabled_port_mask);
+
+	if (enabled_portcount < 1)
+		rte_exit(EXIT_FAILURE, "Failed to initialize Ethernet ports\n");
+
+	/*start Ethernet devices*/
+	ret = start_ethdev_ports(nb_ports, bbdev_enabled_port_mask);
+	if (ret <= 0)
+		rte_exit(EXIT_FAILURE,
+				"Failed to start Ethernet devices on ports\n");
+	check_all_ports_link_status(nb_ports, bbdev_enabled_port_mask);
+
+	/*create bbdev op pools*/
+	bbdev_op_pool[RTE_BBDEV_OP_TURBO_DEC] =
+			rte_bbdev_op_pool_create("bbdev_op_pool_dec",
+			RTE_BBDEV_OP_TURBO_DEC, NB_MBUF, 128, rte_socket_id());
+	bbdev_op_pool[RTE_BBDEV_OP_TURBO_ENC] =
+			rte_bbdev_op_pool_create("bbdev_op_pool_enc",
+			RTE_BBDEV_OP_TURBO_ENC, NB_MBUF, 128, rte_socket_id());
+
+	if ((bbdev_op_pool[RTE_BBDEV_OP_TURBO_DEC] == NULL) ||
+			(bbdev_op_pool[RTE_BBDEV_OP_TURBO_ENC] == NULL))
+		rte_exit(EXIT_FAILURE, "Cannot create bbdev op pools\n");
+
+	/*start DL bbdev device*/
+	if (lcore_setup.rxte_lcores)
+		enable_bbdev(lcore_setup.rxte_lcore_list,
+				lcore_setup.rxte_lcores, 0);
+	/*start UL bbdev device*/
+	if (lcore_setup.rxtd_lcores)
+		enable_bbdev(lcore_setup.rxtd_lcore_list,
+				lcore_setup.rxtd_lcores, 1);
+
+	/*launch per-lcore init on every lcore*/
+	rte_eal_mp_remote_launch(launch_one_lcore, (void *)&lcore_setup,
+			CALL_MASTER);
+
+	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+		if (rte_eal_wait_lcore(lcore_id) < 0)
+			return -1;
+	}
+
+	return 0;
+}
-- 
2.7.4

  parent reply	other threads:[~2017-09-30  1:38 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-30  1:37 [PATCH v1 1/6] bbdev: librte_bbdev library Amr Mokhtar
2017-09-30  1:37 ` [PATCH v1 2/6] bbdev: PMD drivers (null/turbo_sw) Amr Mokhtar
2017-09-30  1:37 ` [PATCH v1 3/6] bbdev: test applications Amr Mokhtar
2017-09-30  1:37 ` Amr Mokhtar [this message]
2017-09-30  1:37 ` [PATCH v1 5/6] bbdev: documentation Amr Mokhtar
2017-09-30  1:37 ` [PATCH v1 6/6] bbdev: auxiliary changes to DPDK framework Amr Mokhtar
2017-10-04 16:14   ` Burakov, Anatoly
2017-10-16  9:00     ` Mokhtar, Amr
2017-10-16 10:03 ` [PATCH v1 1/6] bbdev: librte_bbdev library De Lara Guarch, Pablo
2017-10-18  2:25   ` Mokhtar, Amr

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1506735475-77078-4-git-send-email-amr.mokhtar@intel.com \
    --to=amr.mokhtar@intel.com \
    --cc=chris.macnamara@intel.com \
    --cc=dev@dpdk.org \
    --cc=niall.power@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.