diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h b/platform/linux-dpdk/include/odp_packet_dpdk.h
index bcbe9e8..bcf9aa5 100644
--- a/platform/linux-dpdk/include/odp_packet_dpdk.h
+++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
@@ -50,6 +50,30 @@
 
 #define DPDK_BLOCKING_IO
 
+/*
+ * RX and TX Prefetch, Host, and Write-back threshold values should be
+ * carefully set for optimal performance. Consult the network
+ * controller's datasheet and supporting DPDK documentation for guidance
+ * on how these parameters should be set.
+ */
+#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
+#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
+#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */
+
+/*
+ * These default values are optimized for use with the Intel(R) 82599 10 GbE
+ * Controller and the DPDK ixgbe PMD. Consider using other values for other
+ * network controllers and/or network drivers.
+ */
+#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */
+#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
+#define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
+
+#define MAX_PKT_BURST 16
+#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
+#define RTE_TEST_RX_DESC_DEFAULT 128
+#define RTE_TEST_TX_DESC_DEFAULT 512
+
 /** Packet socket using dpdk mmaped rings for both Rx and Tx */
 typedef struct {
 	odp_buffer_pool_t pool;
diff --git a/platform/linux-dpdk/odp_buffer_pool.c b/platform/linux-dpdk/odp_buffer_pool.c
index de90275..805ce68 100644
--- a/platform/linux-dpdk/odp_buffer_pool.c
+++ b/platform/linux-dpdk/odp_buffer_pool.c
@@ -23,7 +23,7 @@
 #include <odp_packet_dpdk.h>
 
 #define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
-#define NB_MBUF   8192
+#define NB_MBUF   32768
 
 #ifdef POOL_USE_TICKETLOCK
 #include <odp_ticketlock.h>
@@ -112,7 +112,7 @@ odp_buffer_pool_t odp_buffer_pool_create(const char *name,
 
 	pktmbuf_pool =
 		rte_mempool_create(name, NB_MBUF,
-				   MBUF_SIZE, 32,
+				   MBUF_SIZE, MAX_PKT_BURST,
 				   sizeof(struct rte_pktmbuf_pool_private),
 				   rte_pktmbuf_pool_init, NULL,
 				   rte_pktmbuf_init, NULL,
diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c
index 31bfa30..d5c8e80 100644
--- a/platform/linux-dpdk/odp_packet_dpdk.c
+++ b/platform/linux-dpdk/odp_packet_dpdk.c
@@ -26,34 +26,13 @@
 #include <odp_packet_dpdk.h>
 #include <net/if.h>
 
-/*
- * RX and TX Prefetch, Host, and Write-back threshold values should be
- * carefully set for optimal performance. Consult the network
- * controller's datasheet and supporting DPDK documentation for guidance
- * on how these parameters should be set.
- */
-#define RX_PTHRESH 8 /**< Default values of RX prefetch threshold reg. */
-#define RX_HTHRESH 8 /**< Default values of RX host threshold reg. */
-#define RX_WTHRESH 4 /**< Default values of RX write-back threshold reg. */
-
-/*
- * These default values are optimized for use with the Intel(R) 82599 10 GbE
- * Controller and the DPDK ixgbe PMD. Consider using other values for other
- * network controllers and/or network drivers.
- */
-#define TX_PTHRESH 36 /**< Default values of TX prefetch threshold reg. */
-#define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
-#define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */
-
-#define MAX_PKT_BURST 16
-#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
-#define RTE_TEST_RX_DESC_DEFAULT 128
-#define RTE_TEST_TX_DESC_DEFAULT 512
 static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
 static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
 
 static const struct rte_eth_conf port_conf = {
 	.rxmode = {
+		.mq_mode = ETH_MQ_RX_RSS,
+		.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 */
@@ -61,6 +40,12 @@ static const struct rte_eth_conf port_conf = {
 		.jumbo_frame    = 0, /**< Jumbo Frame Support disabled */
 		.hw_strip_crc   = 0, /**< CRC stripped by hardware */
 	},
+	.rx_adv_conf = {
+		.rss_conf = {
+			.rss_key = NULL,
+			.rss_hf = ETH_RSS_IPV4 | ETH_RSS_IPV6,
+		},
+	},
 	.txmode = {
 		.mq_mode = ETH_MQ_TX_NONE,
 	},
@@ -95,60 +80,71 @@ int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
 	ODP_DBG("setup_pkt_dpdk\n");
 
 	static struct ether_addr eth_addr[RTE_MAX_ETHPORTS];
-	uint8_t portid = 0;
-	uint16_t queueid = 0;
-	int ret;
+	static int portinit[RTE_MAX_ETHPORTS];
+	static int qid[RTE_MAX_ETHPORTS];
+	uint8_t portid = 0, num_intf = 2;
+	uint16_t nbrxq = 0, nbtxq = 0;
+	int ret, i;
+
 	printf("dpdk netdev: %s\n", netdev);
 	printf("dpdk pool: %lx\n", pool);
-
 	portid = atoi(netdev);
 	pkt_dpdk->portid = portid;
-	pkt_dpdk->queueid = queueid;
 	pkt_dpdk->pool = pool;
 	printf("dpdk portid: %u\n", portid);
 
-	fflush(stdout);
-	ret = rte_eth_dev_configure(portid, 1, 1, &port_conf);
-	if (ret < 0)
-		ODP_ERR("Cannot configure device: err=%d, port=%u\n",
-			ret, (unsigned) portid);
-
-	rte_eth_macaddr_get(portid, &eth_addr[portid]);
-	ODP_DBG("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
-		(unsigned) portid,
-		eth_addr[portid].addr_bytes[0],
-		eth_addr[portid].addr_bytes[1],
-		eth_addr[portid].addr_bytes[2],
-		eth_addr[portid].addr_bytes[3],
-		eth_addr[portid].addr_bytes[4],
-		eth_addr[portid].addr_bytes[5]);
-
-	/* init one RX queue on each port */
-	fflush(stdout);
-	ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd,
-				     rte_eth_dev_socket_id(portid), &rx_conf,
-				     (struct rte_mempool *)pool);
-	if (ret < 0)
-		ODP_ERR("rte_eth_rx_queue_setup:err=%d, port=%u\n",
-			ret, (unsigned) portid);
-	ODP_DBG("dpdk rx queue setup done\n");
-
-	/* init one TX queue on each port */
-	fflush(stdout);
-	ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd,
-			rte_eth_dev_socket_id(portid), &tx_conf);
-	if (ret < 0)
-		ODP_ERR("rte_eth_tx_queue_setup:err=%d, port=%u\n",
-			ret, (unsigned) portid);
-	ODP_DBG("dpdk tx queue setup done\n");
-
-	/* Start device */
-	ret = rte_eth_dev_start(portid);
-	if (ret < 0)
-		ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n",
-			ret, (unsigned) portid);
-	ODP_DBG("dpdk setup done\n\n");
-
+	nbrxq = odp_sys_core_count() / num_intf;
+	nbtxq = nbrxq;
+	if (portinit[portid] == 0) {
+		fflush(stdout);
+		ret = rte_eth_dev_configure(portid, nbrxq, nbtxq, &port_conf);
+		if (ret < 0)
+			ODP_ERR("Cannot configure device: err=%d, port=%u\n",
+				ret, (unsigned) portid);
+
+		rte_eth_macaddr_get(portid, &eth_addr[portid]);
+		ODP_DBG("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
+			(unsigned) portid,
+			eth_addr[portid].addr_bytes[0],
+			eth_addr[portid].addr_bytes[1],
+			eth_addr[portid].addr_bytes[2],
+			eth_addr[portid].addr_bytes[3],
+			eth_addr[portid].addr_bytes[4],
+			eth_addr[portid].addr_bytes[5]);
+
+		/* init one RX queue on each port */
+		fflush(stdout);
+		for (i = 0; i < nbrxq; i++) {
+			ret = rte_eth_rx_queue_setup(portid, i, nb_rxd,
+					rte_eth_dev_socket_id(portid), &rx_conf,
+					(struct rte_mempool *)pool);
+			if (ret < 0)
+				ODP_ERR("%s rxq:err=%d, port=%u\n",
+					__func__, ret, (unsigned) portid);
+			ODP_DBG("dpdk rx queue setup done\n");
+		}
+
+		/* init one TX queue on each port */
+		fflush(stdout);
+		for (i = 0; i < nbtxq; i++) {
+			ret = rte_eth_tx_queue_setup(portid, i, nb_txd,
+				rte_eth_dev_socket_id(portid), &tx_conf);
+			if (ret < 0)
+				ODP_ERR("%s txq:err=%d, port=%u\n",
+					__func__, ret, (unsigned) portid);
+			ODP_DBG("dpdk tx queue setup done\n");
+		}
+
+		/* Start device */
+		ret = rte_eth_dev_start(portid);
+		if (ret < 0)
+			ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n",
+				ret, (unsigned) portid);
+		ODP_DBG("dpdk setup done\n\n");
+
+		portinit[portid] = 1;
+	}
+	pkt_dpdk->queueid = qid[portid]++;
 
 	return 0;
 }
diff --git a/platform/linux-dpdk/odp_packet_io.c b/platform/linux-dpdk/odp_packet_io.c
index d8d127f..3124175 100644
--- a/platform/linux-dpdk/odp_packet_io.c
+++ b/platform/linux-dpdk/odp_packet_io.c
@@ -230,6 +230,8 @@ int odp_pktio_recv(odp_pktio_t id, odp_packet_t pkt_table[], unsigned len)
 	if (pktio_entry == NULL)
 		return -1;
 
+	odp_pktio_send(id, pkt_table, 0);
+
 	lock_entry(pktio_entry);
 	pkts = recv_pkt_dpdk(&pktio_entry->s.pkt_dpdk, pkt_table, len);
 	unlock_entry(pktio_entry);
