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