176404edcSAsim Jamshed /* for io_module_func def'ns */
276404edcSAsim Jamshed #include "io_module.h"
376404edcSAsim Jamshed /* for mtcp related def'ns */
476404edcSAsim Jamshed #include "mtcp.h"
576404edcSAsim Jamshed /* for errno */
676404edcSAsim Jamshed #include <errno.h>
7dcdbbb98SAsim Jamshed /* for close/optind */
8dcdbbb98SAsim Jamshed #include <unistd.h>
976404edcSAsim Jamshed /* for logging */
1076404edcSAsim Jamshed #include "debug.h"
1176404edcSAsim Jamshed /* for num_devices_* */
1276404edcSAsim Jamshed #include "config.h"
1376404edcSAsim Jamshed /* for rte_max_eth_ports */
1476404edcSAsim Jamshed #include <rte_common.h>
1576404edcSAsim Jamshed /* for rte_eth_rxconf */
1676404edcSAsim Jamshed #include <rte_ethdev.h>
1776404edcSAsim Jamshed /* for delay funcs */
1876404edcSAsim Jamshed #include <rte_cycles.h>
1976404edcSAsim Jamshed /* for ip pesudo-chksum */
2076404edcSAsim Jamshed #include <rte_ip.h>
2176404edcSAsim Jamshed #define ENABLE_STATS_IOCTL		1
2276404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
2376404edcSAsim Jamshed /* for open */
2476404edcSAsim Jamshed #include <fcntl.h>
2576404edcSAsim Jamshed /* for ioctl */
2676404edcSAsim Jamshed #include <sys/ioctl.h>
2776404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
28eac4da1cSM. Asim Jamshed /* for retrieving rte version(s) */
29eac4da1cSM. Asim Jamshed #include <rte_version.h>
3076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
3176404edcSAsim Jamshed /* Essential macros */
3276404edcSAsim Jamshed #define MAX_RX_QUEUE_PER_LCORE		MAX_CPUS
3376404edcSAsim Jamshed #define MAX_TX_QUEUE_PER_PORT		MAX_CPUS
3476404edcSAsim Jamshed 
3576404edcSAsim Jamshed #define MBUF_SIZE 			(2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
3676404edcSAsim Jamshed #define NB_MBUF				8192
3776404edcSAsim Jamshed #define MEMPOOL_CACHE_SIZE		256
38a5e1a556SAsim Jamshed //#define RX_IDLE_ENABLE			1
39a5e1a556SAsim Jamshed #define RX_IDLE_TIMEOUT			1	/* in micro-seconds */
40a5e1a556SAsim Jamshed #define RX_IDLE_THRESH			64
4176404edcSAsim Jamshed 
4276404edcSAsim Jamshed /*
4376404edcSAsim Jamshed  * RX and TX Prefetch, Host, and Write-back threshold values should be
4476404edcSAsim Jamshed  * carefully set for optimal performance. Consult the network
4576404edcSAsim Jamshed  * controller's datasheet and supporting DPDK documentation for guidance
4676404edcSAsim Jamshed  * on how these parameters should be set.
4776404edcSAsim Jamshed  */
4876404edcSAsim Jamshed #define RX_PTHRESH 			8 /**< Default values of RX prefetch threshold reg. */
4976404edcSAsim Jamshed #define RX_HTHRESH 			8 /**< Default values of RX host threshold reg. */
5076404edcSAsim Jamshed #define RX_WTHRESH 			4 /**< Default values of RX write-back threshold reg. */
5176404edcSAsim Jamshed 
5276404edcSAsim Jamshed /*
5376404edcSAsim Jamshed  * These default values are optimized for use with the Intel(R) 82599 10 GbE
5476404edcSAsim Jamshed  * Controller and the DPDK ixgbe PMD. Consider using other values for other
5576404edcSAsim Jamshed  * network controllers and/or network drivers.
5676404edcSAsim Jamshed  */
5776404edcSAsim Jamshed #define TX_PTHRESH 			36 /**< Default values of TX prefetch threshold reg. */
5876404edcSAsim Jamshed #define TX_HTHRESH			0  /**< Default values of TX host threshold reg. */
5976404edcSAsim Jamshed #define TX_WTHRESH			0  /**< Default values of TX write-back threshold reg. */
6076404edcSAsim Jamshed 
6176404edcSAsim Jamshed #define MAX_PKT_BURST			/*32*/64/*128*//*32*/
6276404edcSAsim Jamshed 
6376404edcSAsim Jamshed /*
6476404edcSAsim Jamshed  * Configurable number of RX/TX ring descriptors
6576404edcSAsim Jamshed  */
6676404edcSAsim Jamshed #define RTE_TEST_RX_DESC_DEFAULT	128
6776404edcSAsim Jamshed #define RTE_TEST_TX_DESC_DEFAULT	512
6876404edcSAsim Jamshed 
6976404edcSAsim Jamshed static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
7076404edcSAsim Jamshed static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
7176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
7276404edcSAsim Jamshed /* packet memory pools for storing packet bufs */
7376404edcSAsim Jamshed static struct rte_mempool *pktmbuf_pool[MAX_CPUS] = {NULL};
7476404edcSAsim Jamshed static uint8_t cpu_qid_map[RTE_MAX_ETHPORTS][MAX_CPUS] = {{0}};
7576404edcSAsim Jamshed 
7676404edcSAsim Jamshed //#define DEBUG				1
7776404edcSAsim Jamshed #ifdef DEBUG
7876404edcSAsim Jamshed /* ethernet addresses of ports */
7976404edcSAsim Jamshed static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
8076404edcSAsim Jamshed #endif
8176404edcSAsim Jamshed 
82b88bd7d2SAsim Jamshed static struct rte_eth_dev_info dev_info[RTE_MAX_ETHPORTS];
83b88bd7d2SAsim Jamshed 
8476404edcSAsim Jamshed static struct rte_eth_conf port_conf = {
8576404edcSAsim Jamshed 	.rxmode = {
8676404edcSAsim Jamshed 		.mq_mode	= 	ETH_MQ_RX_RSS,
8776404edcSAsim Jamshed 		.max_rx_pkt_len = 	ETHER_MAX_LEN,
8876404edcSAsim Jamshed 		.split_hdr_size = 	0,
89b69e7ad2SM. Asim Jamshed #if RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0)
9076404edcSAsim Jamshed 		.header_split   = 	0, /**< Header Split disabled */
9176404edcSAsim Jamshed 		.hw_ip_checksum = 	1, /**< IP checksum offload enabled */
9276404edcSAsim Jamshed 		.hw_vlan_filter = 	0, /**< VLAN filtering disabled */
9376404edcSAsim Jamshed 		.jumbo_frame    = 	0, /**< Jumbo Frame Support disabled */
9476404edcSAsim Jamshed 		.hw_strip_crc   = 	1, /**< CRC stripped by hardware */
95eac4da1cSM. Asim Jamshed #else
96eac4da1cSM. Asim Jamshed 		.offloads	=	DEV_RX_OFFLOAD_CHECKSUM,
97eac4da1cSM. Asim Jamshed #endif
9876404edcSAsim Jamshed 	},
9976404edcSAsim Jamshed 	.rx_adv_conf = {
10076404edcSAsim Jamshed 		.rss_conf = {
10176404edcSAsim Jamshed 			.rss_key = 	NULL,
102b2b18834SAsim Jamshed 			.rss_hf = 	ETH_RSS_TCP | ETH_RSS_UDP |
103b2b18834SAsim Jamshed 					ETH_RSS_IP | ETH_RSS_L2_PAYLOAD
10476404edcSAsim Jamshed 		},
10576404edcSAsim Jamshed 	},
10676404edcSAsim Jamshed 	.txmode = {
10776404edcSAsim Jamshed 		.mq_mode = 		ETH_MQ_TX_NONE,
108b69e7ad2SM. Asim Jamshed #if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0)
109eac4da1cSM. Asim Jamshed 		.offloads	=	DEV_TX_OFFLOAD_IPV4_CKSUM |
110eac4da1cSM. Asim Jamshed 					DEV_TX_OFFLOAD_UDP_CKSUM |
111eac4da1cSM. Asim Jamshed 					DEV_TX_OFFLOAD_TCP_CKSUM
112eac4da1cSM. Asim Jamshed #endif
11376404edcSAsim Jamshed 	},
11476404edcSAsim Jamshed };
11576404edcSAsim Jamshed 
11676404edcSAsim Jamshed static const struct rte_eth_rxconf rx_conf = {
11776404edcSAsim Jamshed 	.rx_thresh = {
11876404edcSAsim Jamshed 		.pthresh = 		RX_PTHRESH, /* RX prefetch threshold reg */
11976404edcSAsim Jamshed 		.hthresh = 		RX_HTHRESH, /* RX host threshold reg */
12076404edcSAsim Jamshed 		.wthresh = 		RX_WTHRESH, /* RX write-back threshold reg */
12176404edcSAsim Jamshed 	},
12276404edcSAsim Jamshed 	.rx_free_thresh = 		32,
12376404edcSAsim Jamshed };
12476404edcSAsim Jamshed 
12576404edcSAsim Jamshed static const struct rte_eth_txconf tx_conf = {
12676404edcSAsim Jamshed 	.tx_thresh = {
12776404edcSAsim Jamshed 		.pthresh = 		TX_PTHRESH, /* TX prefetch threshold reg */
12876404edcSAsim Jamshed 		.hthresh = 		TX_HTHRESH, /* TX host threshold reg */
12976404edcSAsim Jamshed 		.wthresh = 		TX_WTHRESH, /* TX write-back threshold reg */
13076404edcSAsim Jamshed 	},
13176404edcSAsim Jamshed 	.tx_free_thresh = 		0, /* Use PMD default values */
13276404edcSAsim Jamshed 	.tx_rs_thresh = 		0, /* Use PMD default values */
133b69e7ad2SM. Asim Jamshed #if RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0)
13476404edcSAsim Jamshed 	/*
13576404edcSAsim Jamshed 	 * As the example won't handle mult-segments and offload cases,
13676404edcSAsim Jamshed 	 * set the flag by default.
13776404edcSAsim Jamshed 	 */
13876404edcSAsim Jamshed 	.txq_flags = 			0x0,
139eac4da1cSM. Asim Jamshed #endif
14076404edcSAsim Jamshed };
14176404edcSAsim Jamshed 
14276404edcSAsim Jamshed struct mbuf_table {
14376404edcSAsim Jamshed 	unsigned len; /* length of queued packets */
14476404edcSAsim Jamshed 	struct rte_mbuf *m_table[MAX_PKT_BURST];
14576404edcSAsim Jamshed };
14676404edcSAsim Jamshed 
14776404edcSAsim Jamshed struct dpdk_private_context {
14876404edcSAsim Jamshed 	struct mbuf_table rmbufs[RTE_MAX_ETHPORTS];
14976404edcSAsim Jamshed 	struct mbuf_table wmbufs[RTE_MAX_ETHPORTS];
15076404edcSAsim Jamshed 	struct rte_mempool *pktmbuf_pool;
15176404edcSAsim Jamshed 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
152a5e1a556SAsim Jamshed #ifdef RX_IDLE_ENABLE
153a5e1a556SAsim Jamshed 	uint8_t rx_idle;
154a5e1a556SAsim Jamshed #endif
15576404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
15676404edcSAsim Jamshed 	int fd;
15776404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
15876404edcSAsim Jamshed } __rte_cache_aligned;
15976404edcSAsim Jamshed 
16076404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
16176404edcSAsim Jamshed /**
16276404edcSAsim Jamshed  * stats struct passed on from user space to the driver
16376404edcSAsim Jamshed  */
16476404edcSAsim Jamshed struct stats_struct {
16576404edcSAsim Jamshed 	uint64_t tx_bytes;
16676404edcSAsim Jamshed 	uint64_t tx_pkts;
16776404edcSAsim Jamshed 	uint64_t rx_bytes;
16876404edcSAsim Jamshed 	uint64_t rx_pkts;
16976404edcSAsim Jamshed 	uint8_t qid;
17076404edcSAsim Jamshed 	uint8_t dev;
17176404edcSAsim Jamshed };
17276404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
17376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
17476404edcSAsim Jamshed void
dpdk_init_handle(struct mtcp_thread_context * ctxt)17576404edcSAsim Jamshed dpdk_init_handle(struct mtcp_thread_context *ctxt)
17676404edcSAsim Jamshed {
17776404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
17876404edcSAsim Jamshed 	int i, j;
17976404edcSAsim Jamshed 	char mempool_name[20];
18076404edcSAsim Jamshed 
18176404edcSAsim Jamshed 	/* create and initialize private I/O module context */
18276404edcSAsim Jamshed 	ctxt->io_private_context = calloc(1, sizeof(struct dpdk_private_context));
18376404edcSAsim Jamshed 	if (ctxt->io_private_context == NULL) {
18476404edcSAsim Jamshed 		TRACE_ERROR("Failed to initialize ctxt->io_private_context: "
18576404edcSAsim Jamshed 			    "Can't allocate memory\n");
18676404edcSAsim Jamshed 		exit(EXIT_FAILURE);
18776404edcSAsim Jamshed 	}
18876404edcSAsim Jamshed 
18976404edcSAsim Jamshed 	sprintf(mempool_name, "mbuf_pool-%d", ctxt->cpu);
19076404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *)ctxt->io_private_context;
19176404edcSAsim Jamshed 	dpc->pktmbuf_pool = pktmbuf_pool[ctxt->cpu];
19276404edcSAsim Jamshed 
19376404edcSAsim Jamshed 	/* set wmbufs correctly */
19476404edcSAsim Jamshed 	for (j = 0; j < g_config.mos->netdev_table->num; j++) {
19576404edcSAsim Jamshed 		/* Allocate wmbufs for each registered port */
19676404edcSAsim Jamshed 		for (i = 0; i < MAX_PKT_BURST; i++) {
19776404edcSAsim Jamshed 			dpc->wmbufs[j].m_table[i] = rte_pktmbuf_alloc(pktmbuf_pool[ctxt->cpu]);
19876404edcSAsim Jamshed 			if (dpc->wmbufs[j].m_table[i] == NULL) {
19976404edcSAsim Jamshed 				TRACE_ERROR("Failed to allocate %d:wmbuf[%d] on device %d!\n",
20076404edcSAsim Jamshed 					    ctxt->cpu, i, j);
20176404edcSAsim Jamshed 				exit(EXIT_FAILURE);
20276404edcSAsim Jamshed 			}
20376404edcSAsim Jamshed 		}
20476404edcSAsim Jamshed 		/* set mbufs queue length to 0 to begin with */
20576404edcSAsim Jamshed 		dpc->wmbufs[j].len = 0;
20676404edcSAsim Jamshed 	}
20776404edcSAsim Jamshed 
20876404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
20976404edcSAsim Jamshed 	dpc->fd = open("/dev/dpdk-iface", O_RDWR);
21076404edcSAsim Jamshed 	if (dpc->fd == -1) {
211c789f6daSAsim Jamshed 		TRACE_ERROR("Can't open /dev/dpdk-iface for context->cpu: %d! "
212c789f6daSAsim Jamshed 			    "Are you using mlx4/mlx5 driver?\n",
21376404edcSAsim Jamshed 			    ctxt->cpu);
21476404edcSAsim Jamshed 	}
21576404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
21676404edcSAsim Jamshed }
21776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
21876404edcSAsim Jamshed int
dpdk_send_pkts(struct mtcp_thread_context * ctxt,int nif)21976404edcSAsim Jamshed dpdk_send_pkts(struct mtcp_thread_context *ctxt, int nif)
22076404edcSAsim Jamshed {
22176404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
22276404edcSAsim Jamshed 	mtcp_manager_t mtcp;
22376404edcSAsim Jamshed 	int ret;
22476404edcSAsim Jamshed 	int qid;
22576404edcSAsim Jamshed 
22676404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *)ctxt->io_private_context;
22776404edcSAsim Jamshed 	mtcp = ctxt->mtcp_manager;
22876404edcSAsim Jamshed 	ret = 0;
22976404edcSAsim Jamshed 	qid = cpu_qid_map[nif][ctxt->cpu];
23076404edcSAsim Jamshed 
23176404edcSAsim Jamshed 	/* if queue is unassigned, skip it.. */
23276404edcSAsim Jamshed 	if (unlikely(qid == 0xFF))
23376404edcSAsim Jamshed 		return 0;
23476404edcSAsim Jamshed 
23576404edcSAsim Jamshed 	/* if there are packets in the queue... flush them out to the wire */
23676404edcSAsim Jamshed 	if (dpc->wmbufs[nif].len >/*= MAX_PKT_BURST*/ 0) {
23776404edcSAsim Jamshed 		struct rte_mbuf **pkts;
23876404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
23976404edcSAsim Jamshed 		struct stats_struct ss;
24076404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
24176404edcSAsim Jamshed 		int cnt = dpc->wmbufs[nif].len;
24276404edcSAsim Jamshed 		pkts = dpc->wmbufs[nif].m_table;
24376404edcSAsim Jamshed #ifdef NETSTAT
24476404edcSAsim Jamshed 		mtcp->nstat.tx_packets[nif] += cnt;
24576404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
246c789f6daSAsim Jamshed 		if (likely(dpc->fd) >= 0) {
24776404edcSAsim Jamshed 			ss.tx_pkts = mtcp->nstat.tx_packets[nif];
24876404edcSAsim Jamshed 			ss.tx_bytes = mtcp->nstat.tx_bytes[nif];
24976404edcSAsim Jamshed 			ss.rx_pkts = mtcp->nstat.rx_packets[nif];
25076404edcSAsim Jamshed 			ss.rx_bytes = mtcp->nstat.rx_bytes[nif];
25176404edcSAsim Jamshed 			ss.qid = ctxt->cpu;
25276404edcSAsim Jamshed 			ss.dev = nif;
25376404edcSAsim Jamshed 			ioctl(dpc->fd, 0, &ss);
254c789f6daSAsim Jamshed 		}
25576404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
25676404edcSAsim Jamshed #endif
25776404edcSAsim Jamshed 		do {
25876404edcSAsim Jamshed 			/* tx cnt # of packets */
25976404edcSAsim Jamshed 			ret = rte_eth_tx_burst(nif, qid,
26076404edcSAsim Jamshed 					       pkts, cnt);
26176404edcSAsim Jamshed 			pkts += ret;
26276404edcSAsim Jamshed 			cnt -= ret;
26376404edcSAsim Jamshed 			/* if not all pkts were sent... then repeat the cycle */
26476404edcSAsim Jamshed 		} while (cnt > 0);
26576404edcSAsim Jamshed 
26676404edcSAsim Jamshed #ifndef SHARE_IO_BUFFER
26776404edcSAsim Jamshed 		int i;
26876404edcSAsim Jamshed 		/* time to allocate fresh mbufs for the queue */
26976404edcSAsim Jamshed 		for (i = 0; i < dpc->wmbufs[nif].len; i++) {
27076404edcSAsim Jamshed 			dpc->wmbufs[nif].m_table[i] = rte_pktmbuf_alloc(pktmbuf_pool[ctxt->cpu]);
27176404edcSAsim Jamshed 			/* error checking */
27276404edcSAsim Jamshed 			if (unlikely(dpc->wmbufs[nif].m_table[i] == NULL)) {
27376404edcSAsim Jamshed 				TRACE_ERROR("Failed to allocate %d:wmbuf[%d] on device %d!\n",
27476404edcSAsim Jamshed 					    ctxt->cpu, i, nif);
27576404edcSAsim Jamshed 				exit(EXIT_FAILURE);
27676404edcSAsim Jamshed 			}
27776404edcSAsim Jamshed 		}
27876404edcSAsim Jamshed #endif
27976404edcSAsim Jamshed 		/* reset the len of mbufs var after flushing of packets */
28076404edcSAsim Jamshed 		dpc->wmbufs[nif].len = 0;
28176404edcSAsim Jamshed 	}
28276404edcSAsim Jamshed 
28376404edcSAsim Jamshed 	return ret;
28476404edcSAsim Jamshed }
28576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
28676404edcSAsim Jamshed uint8_t *
dpdk_get_wptr(struct mtcp_thread_context * ctxt,int nif,uint16_t pktsize)28776404edcSAsim Jamshed dpdk_get_wptr(struct mtcp_thread_context *ctxt, int nif, uint16_t pktsize)
28876404edcSAsim Jamshed {
28976404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
29076404edcSAsim Jamshed 	mtcp_manager_t mtcp;
29176404edcSAsim Jamshed 	struct rte_mbuf *m;
29276404edcSAsim Jamshed 	uint8_t *ptr;
29376404edcSAsim Jamshed 	int len_of_mbuf;
29476404edcSAsim Jamshed 
29576404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
29676404edcSAsim Jamshed 	mtcp = ctxt->mtcp_manager;
29776404edcSAsim Jamshed 
29876404edcSAsim Jamshed 	/* sanity check */
29976404edcSAsim Jamshed 	if (unlikely(dpc->wmbufs[nif].len == MAX_PKT_BURST))
30076404edcSAsim Jamshed 		return NULL;
30176404edcSAsim Jamshed 
30276404edcSAsim Jamshed 	len_of_mbuf = dpc->wmbufs[nif].len;
30376404edcSAsim Jamshed 	m = dpc->wmbufs[nif].m_table[len_of_mbuf];
30476404edcSAsim Jamshed 
30576404edcSAsim Jamshed 	/* retrieve the right write offset */
30676404edcSAsim Jamshed 	ptr = (void *)rte_pktmbuf_mtod(m, struct ether_hdr *);
30776404edcSAsim Jamshed 	m->pkt_len = m->data_len = pktsize;
30876404edcSAsim Jamshed 	m->nb_segs = 1;
30976404edcSAsim Jamshed 	m->next = NULL;
31076404edcSAsim Jamshed 
31176404edcSAsim Jamshed #ifdef NETSTAT
312a834ea89SAsim Jamshed 	mtcp->nstat.tx_bytes[nif] += pktsize + ETHER_OVR;
31376404edcSAsim Jamshed #endif
31476404edcSAsim Jamshed 
31576404edcSAsim Jamshed 	/* increment the len_of_mbuf var */
31676404edcSAsim Jamshed 	dpc->wmbufs[nif].len = len_of_mbuf + 1;
31776404edcSAsim Jamshed 
31876404edcSAsim Jamshed 	return (uint8_t *)ptr;
31976404edcSAsim Jamshed }
32076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
32176404edcSAsim Jamshed void
dpdk_set_wptr(struct mtcp_thread_context * ctxt,int out_nif,int in_nif,int index)32276404edcSAsim Jamshed dpdk_set_wptr(struct mtcp_thread_context *ctxt, int out_nif, int in_nif, int index)
32376404edcSAsim Jamshed {
32476404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
32576404edcSAsim Jamshed 	mtcp_manager_t mtcp;
32676404edcSAsim Jamshed 	int len_of_mbuf;
32776404edcSAsim Jamshed 
32876404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
32976404edcSAsim Jamshed 	mtcp = ctxt->mtcp_manager;
33076404edcSAsim Jamshed 
33176404edcSAsim Jamshed 	/* sanity check */
33276404edcSAsim Jamshed 	if (unlikely(dpc->wmbufs[out_nif].len == MAX_PKT_BURST))
33376404edcSAsim Jamshed 		return;
33476404edcSAsim Jamshed 
33576404edcSAsim Jamshed 	len_of_mbuf = dpc->wmbufs[out_nif].len;
33676404edcSAsim Jamshed 	dpc->wmbufs[out_nif].m_table[len_of_mbuf] =
33776404edcSAsim Jamshed 		dpc->rmbufs[in_nif].m_table[index];
33876404edcSAsim Jamshed 
33976404edcSAsim Jamshed 	dpc->wmbufs[out_nif].m_table[len_of_mbuf]->udata64 = 0;
34076404edcSAsim Jamshed 
34176404edcSAsim Jamshed #ifdef NETSTAT
342a834ea89SAsim Jamshed 	mtcp->nstat.tx_bytes[out_nif] += dpc->rmbufs[in_nif].m_table[index]->pkt_len + ETHER_OVR;
34376404edcSAsim Jamshed #endif
34476404edcSAsim Jamshed 
34576404edcSAsim Jamshed 	/* increment the len_of_mbuf var */
34676404edcSAsim Jamshed 	dpc->wmbufs[out_nif].len = len_of_mbuf + 1;
34776404edcSAsim Jamshed 
34876404edcSAsim Jamshed 	return;
34976404edcSAsim Jamshed }
35076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
35176404edcSAsim Jamshed static inline void
free_pkts(struct rte_mbuf ** mtable,unsigned len)35276404edcSAsim Jamshed free_pkts(struct rte_mbuf **mtable, unsigned len)
35376404edcSAsim Jamshed {
35476404edcSAsim Jamshed 	int i;
35576404edcSAsim Jamshed 
35676404edcSAsim Jamshed 	/* free the freaking packets */
35776404edcSAsim Jamshed 	for (i = 0; i < len; i++) {
35876404edcSAsim Jamshed 		if (mtable[i]->udata64 == 1) {
35976404edcSAsim Jamshed 			rte_pktmbuf_free_seg(mtable[i]);
36076404edcSAsim Jamshed 			RTE_MBUF_PREFETCH_TO_FREE(mtable[i+1]);
36176404edcSAsim Jamshed 		}
36276404edcSAsim Jamshed 	}
36376404edcSAsim Jamshed }
36476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
36576404edcSAsim Jamshed int32_t
dpdk_recv_pkts(struct mtcp_thread_context * ctxt,int ifidx)36676404edcSAsim Jamshed dpdk_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx)
36776404edcSAsim Jamshed {
36876404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
36976404edcSAsim Jamshed 	int ret;
37076404edcSAsim Jamshed 	uint8_t qid;
37176404edcSAsim Jamshed 
37276404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
37376404edcSAsim Jamshed 	qid = cpu_qid_map[ifidx][ctxt->cpu];
37476404edcSAsim Jamshed 
37576404edcSAsim Jamshed 	/* if queue is unassigned, skip it.. */
37676404edcSAsim Jamshed 	if (qid == 0xFF)
37776404edcSAsim Jamshed 		return 0;
37876404edcSAsim Jamshed 
37976404edcSAsim Jamshed 	if (dpc->rmbufs[ifidx].len != 0) {
38076404edcSAsim Jamshed 		free_pkts(dpc->rmbufs[ifidx].m_table, dpc->rmbufs[ifidx].len);
38176404edcSAsim Jamshed 		dpc->rmbufs[ifidx].len = 0;
38276404edcSAsim Jamshed 	}
38376404edcSAsim Jamshed 
38476404edcSAsim Jamshed 	ret = rte_eth_rx_burst((uint8_t)ifidx, qid,
38576404edcSAsim Jamshed 			       dpc->pkts_burst, MAX_PKT_BURST);
386a5e1a556SAsim Jamshed #ifdef RX_IDLE_ENABLE
387a5e1a556SAsim Jamshed 	dpc->rx_idle = (likely(ret != 0)) ? 0 : dpc->rx_idle + 1;
388a5e1a556SAsim Jamshed #endif
38976404edcSAsim Jamshed 	dpc->rmbufs[ifidx].len = ret;
39076404edcSAsim Jamshed 
39176404edcSAsim Jamshed 	return ret;
39276404edcSAsim Jamshed }
39376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
39476404edcSAsim Jamshed uint8_t *
dpdk_get_rptr(struct mtcp_thread_context * ctxt,int ifidx,int index,uint16_t * len)39576404edcSAsim Jamshed dpdk_get_rptr(struct mtcp_thread_context *ctxt, int ifidx, int index, uint16_t *len)
39676404edcSAsim Jamshed {
39776404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
39876404edcSAsim Jamshed 	struct rte_mbuf *m;
39976404edcSAsim Jamshed 	uint8_t *pktbuf;
40076404edcSAsim Jamshed 
40176404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
40276404edcSAsim Jamshed 
40376404edcSAsim Jamshed 
40476404edcSAsim Jamshed 	m = dpc->pkts_burst[index];
40576404edcSAsim Jamshed 	/* tag to check if the packet is a local or a forwarded pkt */
40676404edcSAsim Jamshed 	m->udata64 = 1;
40776404edcSAsim Jamshed 	/* don't enable pre-fetching... performance goes down */
40876404edcSAsim Jamshed 	//rte_prefetch0(rte_pktmbuf_mtod(m, void *));
40976404edcSAsim Jamshed 	*len = m->pkt_len;
41076404edcSAsim Jamshed 	pktbuf = rte_pktmbuf_mtod(m, uint8_t *);
41176404edcSAsim Jamshed 
41276404edcSAsim Jamshed 	/* enqueue the pkt ptr in mbuf */
41376404edcSAsim Jamshed 	dpc->rmbufs[ifidx].m_table[index] = m;
41476404edcSAsim Jamshed 
41576404edcSAsim Jamshed 	return pktbuf;
41676404edcSAsim Jamshed }
41776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
41876404edcSAsim Jamshed int
dpdk_get_nif(struct ifreq * ifr)41976404edcSAsim Jamshed dpdk_get_nif(struct ifreq *ifr)
42076404edcSAsim Jamshed {
42176404edcSAsim Jamshed 	int i;
42276404edcSAsim Jamshed 	static int num_dev = -1;
42376404edcSAsim Jamshed 	static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
42476404edcSAsim Jamshed 	/* get mac addr entries of 'detected' dpdk ports */
42576404edcSAsim Jamshed 	if (num_dev < 0) {
426b69e7ad2SM. Asim Jamshed #if RTE_VERSION < RTE_VERSION_NUM(18, 5, 0, 0)
42776404edcSAsim Jamshed 		num_dev = rte_eth_dev_count();
428eac4da1cSM. Asim Jamshed #else
429eac4da1cSM. Asim Jamshed 		num_dev = rte_eth_dev_count_avail();
430eac4da1cSM. Asim Jamshed #endif
43176404edcSAsim Jamshed 		for (i = 0; i < num_dev; i++)
43276404edcSAsim Jamshed 			rte_eth_macaddr_get(i, &ports_eth_addr[i]);
43376404edcSAsim Jamshed 	}
43476404edcSAsim Jamshed 
43576404edcSAsim Jamshed 	for (i = 0; i < num_dev; i++)
43676404edcSAsim Jamshed 		if (!memcmp(&ifr->ifr_addr.sa_data[0], &ports_eth_addr[i], ETH_ALEN))
43776404edcSAsim Jamshed 			return i;
43876404edcSAsim Jamshed 
43976404edcSAsim Jamshed 	return -1;
44076404edcSAsim Jamshed }
44176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
442a5e1a556SAsim Jamshed int32_t
dpdk_select(struct mtcp_thread_context * ctxt)443a5e1a556SAsim Jamshed dpdk_select(struct mtcp_thread_context *ctxt)
444a5e1a556SAsim Jamshed {
445a5e1a556SAsim Jamshed #ifdef RX_IDLE_ENABLE
446a5e1a556SAsim Jamshed 	struct dpdk_private_context *dpc;
447a5e1a556SAsim Jamshed 
448a5e1a556SAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
449a5e1a556SAsim Jamshed 	if (dpc->rx_idle > RX_IDLE_THRESH) {
450a5e1a556SAsim Jamshed 		dpc->rx_idle = 0;
451a5e1a556SAsim Jamshed 		usleep(RX_IDLE_TIMEOUT);
452a5e1a556SAsim Jamshed 	}
453a5e1a556SAsim Jamshed #endif
454a5e1a556SAsim Jamshed 	return 0;
455a5e1a556SAsim Jamshed }
456a5e1a556SAsim Jamshed /*----------------------------------------------------------------------------*/
45776404edcSAsim Jamshed void
dpdk_destroy_handle(struct mtcp_thread_context * ctxt)45876404edcSAsim Jamshed dpdk_destroy_handle(struct mtcp_thread_context *ctxt)
45976404edcSAsim Jamshed {
46076404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
46176404edcSAsim Jamshed 	int i;
46276404edcSAsim Jamshed 
46376404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
46476404edcSAsim Jamshed 
46576404edcSAsim Jamshed 	/* free wmbufs */
46676404edcSAsim Jamshed 	for (i = 0; i < g_config.mos->netdev_table->num; i++)
46776404edcSAsim Jamshed 		free_pkts(dpc->wmbufs[i].m_table, MAX_PKT_BURST);
46876404edcSAsim Jamshed 
46976404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
47076404edcSAsim Jamshed 	/* free fd */
471c789f6daSAsim Jamshed 	if (dpc->fd >= 0)
47276404edcSAsim Jamshed 		close(dpc->fd);
47376404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
47476404edcSAsim Jamshed 
47576404edcSAsim Jamshed 	/* free it all up */
47676404edcSAsim Jamshed 	free(dpc);
47776404edcSAsim Jamshed }
47876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
47976404edcSAsim Jamshed static void
check_all_ports_link_status(uint8_t port_num,uint32_t port_mask)48076404edcSAsim Jamshed check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
48176404edcSAsim Jamshed {
48276404edcSAsim Jamshed #define CHECK_INTERVAL 			100 /* 100ms */
48376404edcSAsim Jamshed #define MAX_CHECK_TIME 			90 /* 9s (90 * 100ms) in total */
48476404edcSAsim Jamshed 
48576404edcSAsim Jamshed 	uint8_t portid, count, all_ports_up, print_flag = 0;
48676404edcSAsim Jamshed 	struct rte_eth_link link;
48776404edcSAsim Jamshed 
48876404edcSAsim Jamshed 	printf("\nChecking link status");
48976404edcSAsim Jamshed 	fflush(stdout);
49076404edcSAsim Jamshed 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
49176404edcSAsim Jamshed 		all_ports_up = 1;
49276404edcSAsim Jamshed 		for (portid = 0; portid < port_num; portid++) {
49376404edcSAsim Jamshed 			if ((port_mask & (1 << portid)) == 0)
49476404edcSAsim Jamshed 				continue;
49576404edcSAsim Jamshed 			memset(&link, 0, sizeof(link));
49676404edcSAsim Jamshed 			rte_eth_link_get_nowait(portid, &link);
49776404edcSAsim Jamshed 			/* print link status if flag set */
49876404edcSAsim Jamshed 			if (print_flag == 1) {
49976404edcSAsim Jamshed 				if (link.link_status)
50076404edcSAsim Jamshed 					printf("Port %d Link Up - speed %u "
50176404edcSAsim Jamshed 						"Mbps - %s\n", (uint8_t)portid,
50276404edcSAsim Jamshed 						(unsigned)link.link_speed,
50376404edcSAsim Jamshed 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
50476404edcSAsim Jamshed 					("full-duplex") : ("half-duplex\n"));
50576404edcSAsim Jamshed 				else
50676404edcSAsim Jamshed 					printf("Port %d Link Down\n",
50776404edcSAsim Jamshed 						(uint8_t)portid);
50876404edcSAsim Jamshed 				continue;
50976404edcSAsim Jamshed 			}
51076404edcSAsim Jamshed 			/* clear all_ports_up flag if any link down */
51176404edcSAsim Jamshed 			if (link.link_status == 0) {
51276404edcSAsim Jamshed 				all_ports_up = 0;
51376404edcSAsim Jamshed 				break;
51476404edcSAsim Jamshed 			}
51576404edcSAsim Jamshed 		}
51676404edcSAsim Jamshed 		/* after finally printing all link status, get out */
51776404edcSAsim Jamshed 		if (print_flag == 1)
51876404edcSAsim Jamshed 			break;
51976404edcSAsim Jamshed 
52076404edcSAsim Jamshed 		if (all_ports_up == 0) {
52176404edcSAsim Jamshed 			printf(".");
52276404edcSAsim Jamshed 			fflush(stdout);
52376404edcSAsim Jamshed 			rte_delay_ms(CHECK_INTERVAL);
52476404edcSAsim Jamshed 		}
52576404edcSAsim Jamshed 
52676404edcSAsim Jamshed 		/* set the print_flag if all ports up or timeout */
52776404edcSAsim Jamshed 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
52876404edcSAsim Jamshed 			print_flag = 1;
52976404edcSAsim Jamshed 			printf("done\n");
53076404edcSAsim Jamshed 		}
53176404edcSAsim Jamshed 	}
53276404edcSAsim Jamshed }
53376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
53476404edcSAsim Jamshed int32_t
dpdk_dev_ioctl(struct mtcp_thread_context * ctx,int nif,int cmd,void * argp)53576404edcSAsim Jamshed dpdk_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp)
53676404edcSAsim Jamshed {
53776404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
53876404edcSAsim Jamshed 	struct rte_mbuf *m;
53976404edcSAsim Jamshed 	int len_of_mbuf;
54076404edcSAsim Jamshed 	struct iphdr *iph;
54176404edcSAsim Jamshed 	struct tcphdr *tcph;
54276404edcSAsim Jamshed 	RssInfo *rss_i;
543b88bd7d2SAsim Jamshed 	void **argpptr = (void **)argp;
544b88bd7d2SAsim Jamshed 
545b88bd7d2SAsim Jamshed 	if (cmd == DRV_NAME) {
546b88bd7d2SAsim Jamshed 		*argpptr = (void *)dev_info->driver_name;
547b88bd7d2SAsim Jamshed 		return 0;
548b88bd7d2SAsim Jamshed 	}
54976404edcSAsim Jamshed 
55076404edcSAsim Jamshed 	iph = (struct iphdr *)argp;
55176404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *)ctx->io_private_context;
55276404edcSAsim Jamshed 	len_of_mbuf = dpc->wmbufs[nif].len;
55376404edcSAsim Jamshed 	rss_i = NULL;
55476404edcSAsim Jamshed 
55576404edcSAsim Jamshed 	switch (cmd) {
55676404edcSAsim Jamshed 	case PKT_TX_IP_CSUM:
55776404edcSAsim Jamshed 		m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1];
558522d5c66SAsim Jamshed 		m->ol_flags = PKT_TX_IP_CKSUM | PKT_TX_IPV4;
55976404edcSAsim Jamshed 		m->l2_len = sizeof(struct ether_hdr);
56076404edcSAsim Jamshed 		m->l3_len = (iph->ihl<<2);
56176404edcSAsim Jamshed 		break;
56276404edcSAsim Jamshed 	case PKT_TX_TCP_CSUM:
56376404edcSAsim Jamshed 		m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1];
56476404edcSAsim Jamshed 		tcph = (struct tcphdr *)((unsigned char *)iph + (iph->ihl<<2));
56576404edcSAsim Jamshed 		m->ol_flags |= PKT_TX_TCP_CKSUM;
56676404edcSAsim Jamshed 		tcph->check = rte_ipv4_phdr_cksum((struct ipv4_hdr *)iph, m->ol_flags);
56776404edcSAsim Jamshed 		break;
56876404edcSAsim Jamshed 	case PKT_RX_RSS:
56976404edcSAsim Jamshed 		rss_i = (RssInfo *)argp;
57076404edcSAsim Jamshed 		m = dpc->pkts_burst[rss_i->pktidx];
57176404edcSAsim Jamshed 		rss_i->hash_value = m->hash.rss;
57276404edcSAsim Jamshed 		break;
57376404edcSAsim Jamshed 	default:
57476404edcSAsim Jamshed 		goto dev_ioctl_err;
57576404edcSAsim Jamshed 	}
57676404edcSAsim Jamshed 
57776404edcSAsim Jamshed 	return 0;
57876404edcSAsim Jamshed  dev_ioctl_err:
57976404edcSAsim Jamshed 	return -1;
58076404edcSAsim Jamshed }
58176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
58276404edcSAsim Jamshed void
dpdk_load_module_upper_half(void)58376404edcSAsim Jamshed dpdk_load_module_upper_half(void)
58476404edcSAsim Jamshed {
58576404edcSAsim Jamshed 	int cpu = g_config.mos->num_cores, ret;
58676404edcSAsim Jamshed 	uint32_t cpumask = 0;
58776404edcSAsim Jamshed 	char cpumaskbuf[10];
58876404edcSAsim Jamshed 	char mem_channels[5];
58976404edcSAsim Jamshed 
59076404edcSAsim Jamshed 	/* set the log level */
59114192b47Sintel-lab #if RTE_VERSION < RTE_VERSION_NUM(17, 5, 0, 0)
59276404edcSAsim Jamshed 	rte_set_log_type(RTE_LOGTYPE_PMD, 0);
59376404edcSAsim Jamshed 	rte_set_log_type(RTE_LOGTYPE_MALLOC, 0);
59476404edcSAsim Jamshed 	rte_set_log_type(RTE_LOGTYPE_MEMPOOL, 0);
59576404edcSAsim Jamshed 	rte_set_log_type(RTE_LOGTYPE_RING, 0);
59676404edcSAsim Jamshed 	rte_set_log_level(RTE_LOG_WARNING);
5970be44444SAsim Jamshed #else
5980be44444SAsim Jamshed 	rte_log_set_level(RTE_LOGTYPE_PMD, 0);
5990be44444SAsim Jamshed 	rte_log_set_level(RTE_LOGTYPE_MALLOC, 0);
6000be44444SAsim Jamshed 	rte_log_set_level(RTE_LOGTYPE_MEMPOOL, 0);
6010be44444SAsim Jamshed 	rte_log_set_level(RTE_LOGTYPE_RING, 0);
6020be44444SAsim Jamshed 	rte_log_set_level(RTE_LOG_WARNING, 0);
6030be44444SAsim Jamshed #endif
60476404edcSAsim Jamshed 	/* get the cpu mask */
60576404edcSAsim Jamshed 	for (ret = 0; ret < cpu; ret++)
60676404edcSAsim Jamshed 		cpumask = (cpumask | (1 << ret));
60776404edcSAsim Jamshed 	sprintf(cpumaskbuf, "%X", cpumask);
60876404edcSAsim Jamshed 
60976404edcSAsim Jamshed 	/* get the mem channels per socket */
61076404edcSAsim Jamshed 	if (g_config.mos->nb_mem_channels == 0) {
61176404edcSAsim Jamshed 		TRACE_ERROR("DPDK module requires # of memory channels "
61276404edcSAsim Jamshed 				"per socket parameter!\n");
61376404edcSAsim Jamshed 		exit(EXIT_FAILURE);
61476404edcSAsim Jamshed 	}
61576404edcSAsim Jamshed 	sprintf(mem_channels, "%d", g_config.mos->nb_mem_channels);
61676404edcSAsim Jamshed 
61776404edcSAsim Jamshed 	/* initialize the rte env first, what a waste of implementation effort!  */
61876404edcSAsim Jamshed 	char *argv[] = {"",
61976404edcSAsim Jamshed 			"-c",
62076404edcSAsim Jamshed 			cpumaskbuf,
62176404edcSAsim Jamshed 			"-n",
62276404edcSAsim Jamshed 			mem_channels,
62376404edcSAsim Jamshed 			"--proc-type=auto",
62476404edcSAsim Jamshed 			""
62576404edcSAsim Jamshed 	};
62676404edcSAsim Jamshed 	const int argc = 6;
62776404edcSAsim Jamshed 
62876404edcSAsim Jamshed 	/*
62976404edcSAsim Jamshed 	 * re-set getopt extern variable optind.
63076404edcSAsim Jamshed 	 * this issue was a bitch to debug
63176404edcSAsim Jamshed 	 * rte_eal_init() internally uses getopt() syscall
63276404edcSAsim Jamshed 	 * mtcp applications that also use an `external' getopt
63376404edcSAsim Jamshed 	 * will cause a violent crash if optind is not reset to zero
63476404edcSAsim Jamshed 	 * prior to calling the func below...
63576404edcSAsim Jamshed 	 * see man getopt(3) for more details
63676404edcSAsim Jamshed 	 */
63776404edcSAsim Jamshed 	optind = 0;
63876404edcSAsim Jamshed 
63976404edcSAsim Jamshed 	/* initialize the dpdk eal env */
64076404edcSAsim Jamshed 	ret = rte_eal_init(argc, argv);
64176404edcSAsim Jamshed 	if (ret < 0)
64276404edcSAsim Jamshed 		rte_exit(EXIT_FAILURE, "Invalid EAL args!\n");
64376404edcSAsim Jamshed 
64476404edcSAsim Jamshed }
64576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
64676404edcSAsim Jamshed void
dpdk_load_module_lower_half(void)64776404edcSAsim Jamshed dpdk_load_module_lower_half(void)
64876404edcSAsim Jamshed {
64976404edcSAsim Jamshed 	int portid, rxlcore_id, ret;
65076404edcSAsim Jamshed 	struct rte_eth_fc_conf fc_conf;	/* for Ethernet flow control settings */
65176404edcSAsim Jamshed 	/* setting the rss key */
65276404edcSAsim Jamshed 	static const uint8_t key[] = {
65376404edcSAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
65476404edcSAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
65576404edcSAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
656b88bd7d2SAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
657b88bd7d2SAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
658b88bd7d2SAsim Jamshed 		0x05, 0x05
65976404edcSAsim Jamshed 	};
66076404edcSAsim Jamshed 
661cfb1a230SAsim Jamshed 	port_conf.rx_adv_conf.rss_conf.rss_key = (uint8_t *)key;
66276404edcSAsim Jamshed 	port_conf.rx_adv_conf.rss_conf.rss_key_len = sizeof(key);
66376404edcSAsim Jamshed 
66476404edcSAsim Jamshed 	/* resetting cpu_qid mapping */
66576404edcSAsim Jamshed 	memset(cpu_qid_map, 0xFF, sizeof(cpu_qid_map));
66676404edcSAsim Jamshed 
66776404edcSAsim Jamshed 	if (!g_config.mos->multiprocess
66876404edcSAsim Jamshed 			|| (g_config.mos->multiprocess && g_config.mos->multiprocess_is_master)) {
66976404edcSAsim Jamshed 		for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) {
67076404edcSAsim Jamshed 			char name[20];
67176404edcSAsim Jamshed 			sprintf(name, "mbuf_pool-%d", rxlcore_id);
67276404edcSAsim Jamshed 			/* create the mbuf pools */
67376404edcSAsim Jamshed 			pktmbuf_pool[rxlcore_id] =
67476404edcSAsim Jamshed 				rte_mempool_create(name, NB_MBUF,
67576404edcSAsim Jamshed 						   MBUF_SIZE, MEMPOOL_CACHE_SIZE,
67676404edcSAsim Jamshed 						   sizeof(struct rte_pktmbuf_pool_private),
67776404edcSAsim Jamshed 						   rte_pktmbuf_pool_init, NULL,
67876404edcSAsim Jamshed 						   rte_pktmbuf_init, NULL,
67976404edcSAsim Jamshed 						   rte_lcore_to_socket_id(rxlcore_id), 0);
68076404edcSAsim Jamshed 			if (pktmbuf_pool[rxlcore_id] == NULL)
68176404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
68276404edcSAsim Jamshed 		}
68376404edcSAsim Jamshed 
68476404edcSAsim Jamshed 		/* Initialise each port */
68576404edcSAsim Jamshed 		for (portid = 0; portid < g_config.mos->netdev_table->num; portid++) {
68676404edcSAsim Jamshed 			int num_queue = 0, eth_idx, i, queue_id;
68776404edcSAsim Jamshed 			for (eth_idx = 0; eth_idx < g_config.mos->netdev_table->num; eth_idx++)
68876404edcSAsim Jamshed 				if (portid == g_config.mos->netdev_table->ent[eth_idx]->ifindex)
68976404edcSAsim Jamshed 					break;
69076404edcSAsim Jamshed 			if (eth_idx == g_config.mos->netdev_table->num)
69176404edcSAsim Jamshed 				continue;
69276404edcSAsim Jamshed 			for (i = 0; i < sizeof(uint64_t) * 8; i++)
69376404edcSAsim Jamshed 				if (g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << i))
69476404edcSAsim Jamshed 					num_queue++;
69576404edcSAsim Jamshed 
696eac4da1cSM. Asim Jamshed 			/* check port capabilities */
697eac4da1cSM. Asim Jamshed 			rte_eth_dev_info_get(portid, &dev_info[portid]);
698eac4da1cSM. Asim Jamshed 
699b69e7ad2SM. Asim Jamshed #if RTE_VERSION >= RTE_VERSION_NUM(18, 2, 0, 0)
700eac4da1cSM. Asim Jamshed 			/* re-adjust rss_hf */
701eac4da1cSM. Asim Jamshed 			port_conf.rx_adv_conf.rss_conf.rss_hf &= dev_info[portid].flow_type_rss_offloads;
702eac4da1cSM. Asim Jamshed #endif
70376404edcSAsim Jamshed 			/* set 'num_queues' (used for GetRSSCPUCore() in util.c) */
70476404edcSAsim Jamshed 			num_queues = num_queue;
70576404edcSAsim Jamshed 
70676404edcSAsim Jamshed 			/* init port */
70776404edcSAsim Jamshed 			printf("Initializing port %u... ", (unsigned) portid);
70876404edcSAsim Jamshed 			fflush(stdout);
70976404edcSAsim Jamshed 			ret = rte_eth_dev_configure(portid, num_queue, num_queue,
71076404edcSAsim Jamshed 										&port_conf);
71176404edcSAsim Jamshed 			if (ret < 0)
71276404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Cannot configure device:"
71376404edcSAsim Jamshed 									   "err=%d, port=%u\n",
71476404edcSAsim Jamshed 									   ret, (unsigned) portid);
71576404edcSAsim Jamshed 
71676404edcSAsim Jamshed 			/* init one RX queue per CPU */
71776404edcSAsim Jamshed 			fflush(stdout);
71876404edcSAsim Jamshed #ifdef DEBUG
71976404edcSAsim Jamshed 			rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
72076404edcSAsim Jamshed #endif
72176404edcSAsim Jamshed 			queue_id = 0;
72276404edcSAsim Jamshed 			for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) {
72376404edcSAsim Jamshed 				if (!(g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << rxlcore_id)))
72476404edcSAsim Jamshed 					continue;
72576404edcSAsim Jamshed 				ret = rte_eth_rx_queue_setup(portid, queue_id, nb_rxd,
72676404edcSAsim Jamshed 						rte_eth_dev_socket_id(portid), &rx_conf,
72776404edcSAsim Jamshed 						pktmbuf_pool[rxlcore_id]);
72876404edcSAsim Jamshed 				if (ret < 0)
72976404edcSAsim Jamshed 					rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:"
73076404edcSAsim Jamshed 										   "err=%d, port=%u, queueid: %d\n",
73176404edcSAsim Jamshed 										   ret, (unsigned) portid, rxlcore_id);
73276404edcSAsim Jamshed 				cpu_qid_map[portid][rxlcore_id] = queue_id++;
73376404edcSAsim Jamshed 			}
73476404edcSAsim Jamshed 
73576404edcSAsim Jamshed 			/* init one TX queue on each port per CPU (this is redundant for
73676404edcSAsim Jamshed 			 * this app) */
73776404edcSAsim Jamshed 			fflush(stdout);
73876404edcSAsim Jamshed 			queue_id = 0;
73976404edcSAsim Jamshed 			for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) {
74076404edcSAsim Jamshed 				if (!(g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << rxlcore_id)))
74176404edcSAsim Jamshed 					continue;
74276404edcSAsim Jamshed 				ret = rte_eth_tx_queue_setup(portid, queue_id++, nb_txd,
74376404edcSAsim Jamshed 						rte_eth_dev_socket_id(portid), &tx_conf);
74476404edcSAsim Jamshed 				if (ret < 0)
74576404edcSAsim Jamshed 					rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:"
74676404edcSAsim Jamshed 										   "err=%d, port=%u, queueid: %d\n",
74776404edcSAsim Jamshed 										   ret, (unsigned) portid, rxlcore_id);
74876404edcSAsim Jamshed 			}
74976404edcSAsim Jamshed 
75076404edcSAsim Jamshed 			/* Start device */
75176404edcSAsim Jamshed 			ret = rte_eth_dev_start(portid);
75276404edcSAsim Jamshed 			if (ret < 0)
75376404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n",
75476404edcSAsim Jamshed 									   ret, (unsigned) portid);
75576404edcSAsim Jamshed 
75676404edcSAsim Jamshed 			printf("done: \n");
75776404edcSAsim Jamshed 			rte_eth_promiscuous_enable(portid);
75876404edcSAsim Jamshed 
75976404edcSAsim Jamshed 			/* retrieve current flow control settings per port */
76076404edcSAsim Jamshed 			memset(&fc_conf, 0, sizeof(fc_conf));
76176404edcSAsim Jamshed 			ret = rte_eth_dev_flow_ctrl_get(portid, &fc_conf);
76276404edcSAsim Jamshed 			if (ret != 0) {
76376404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Failed to get flow control info!\n");
76476404edcSAsim Jamshed 			}
76576404edcSAsim Jamshed 
76676404edcSAsim Jamshed 			/* and just disable the rx/tx flow control */
76776404edcSAsim Jamshed 			fc_conf.mode = RTE_FC_NONE;
76876404edcSAsim Jamshed 			ret = rte_eth_dev_flow_ctrl_set(portid, &fc_conf);
76976404edcSAsim Jamshed 			if (ret != 0) {
77076404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Failed to set flow control info!: errno: %d\n",
77176404edcSAsim Jamshed 					 ret);
77276404edcSAsim Jamshed 			}
77376404edcSAsim Jamshed 
77476404edcSAsim Jamshed #ifdef DEBUG
77576404edcSAsim Jamshed 			printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
77676404edcSAsim Jamshed 					(unsigned) portid,
77776404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[0],
77876404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[1],
77976404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[2],
78076404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[3],
78176404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[4],
78276404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[5]);
78376404edcSAsim Jamshed #endif
7843ae9e016SAsim Jamshed 			/* only check for link status if the thread is master */
7853ae9e016SAsim Jamshed 			check_all_ports_link_status(g_config.mos->netdev_table->num, 0xFFFFFFFF);
78676404edcSAsim Jamshed 		}
78776404edcSAsim Jamshed 	} else { /* g_config.mos->multiprocess && !g_config.mos->multiprocess_is_master */
78876404edcSAsim Jamshed 		for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) {
78976404edcSAsim Jamshed 			char name[20];
79076404edcSAsim Jamshed 			sprintf(name, "mbuf_pool-%d", rxlcore_id);
79176404edcSAsim Jamshed 			/* initialize the mbuf pools */
79276404edcSAsim Jamshed 			pktmbuf_pool[rxlcore_id] =
79376404edcSAsim Jamshed 				rte_mempool_lookup(name);
79476404edcSAsim Jamshed 			if (pktmbuf_pool[rxlcore_id] == NULL)
79576404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
7963ae9e016SAsim Jamshed 			for (portid = 0; portid < g_config.mos->netdev_table->num; portid++)
7973ae9e016SAsim Jamshed 				cpu_qid_map[portid][rxlcore_id] = rxlcore_id;
79876404edcSAsim Jamshed 		}
7993ae9e016SAsim Jamshed 		/* set 'num_queues' (used for GetRSSCPUCore() in util.c) */
8003ae9e016SAsim Jamshed 		num_queues = g_config.mos->num_cores;
80176404edcSAsim Jamshed 	}
80276404edcSAsim Jamshed 
80376404edcSAsim Jamshed }
80476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
80576404edcSAsim Jamshed io_module_func dpdk_module_func = {
80676404edcSAsim Jamshed 	.load_module_upper_half		   = dpdk_load_module_upper_half,
80776404edcSAsim Jamshed 	.load_module_lower_half		   = dpdk_load_module_lower_half,
80876404edcSAsim Jamshed 	.init_handle		   = dpdk_init_handle,
80976404edcSAsim Jamshed 	.link_devices		   = NULL,
81076404edcSAsim Jamshed 	.release_pkt		   = NULL,
81176404edcSAsim Jamshed 	.send_pkts		   = dpdk_send_pkts,
81276404edcSAsim Jamshed 	.get_wptr   		   = dpdk_get_wptr,
81376404edcSAsim Jamshed 	.recv_pkts		   = dpdk_recv_pkts,
81476404edcSAsim Jamshed 	.get_rptr	   	   = dpdk_get_rptr,
81576404edcSAsim Jamshed 	.get_nif		   = dpdk_get_nif,
816a5e1a556SAsim Jamshed 	.select			   = dpdk_select,
81776404edcSAsim Jamshed 	.destroy_handle		   = dpdk_destroy_handle,
81876404edcSAsim Jamshed 	.dev_ioctl		   = dpdk_dev_ioctl,
81976404edcSAsim Jamshed 	.set_wptr		   = dpdk_set_wptr,
82076404edcSAsim Jamshed };
82176404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
82276404edcSAsim Jamshed 
823