1*76404edcSAsim Jamshed /* for io_module_func def'ns */
2*76404edcSAsim Jamshed #include "io_module.h"
3*76404edcSAsim Jamshed /* for mtcp related def'ns */
4*76404edcSAsim Jamshed #include "mtcp.h"
5*76404edcSAsim Jamshed /* for errno */
6*76404edcSAsim Jamshed #include <errno.h>
7*76404edcSAsim Jamshed /* for logging */
8*76404edcSAsim Jamshed #include "debug.h"
9*76404edcSAsim Jamshed /* for num_devices_* */
10*76404edcSAsim Jamshed #include "config.h"
11*76404edcSAsim Jamshed /* for rte_max_eth_ports */
12*76404edcSAsim Jamshed #include <rte_common.h>
13*76404edcSAsim Jamshed /* for rte_eth_rxconf */
14*76404edcSAsim Jamshed #include <rte_ethdev.h>
15*76404edcSAsim Jamshed /* for delay funcs */
16*76404edcSAsim Jamshed #include <rte_cycles.h>
17*76404edcSAsim Jamshed /* for ip pesudo-chksum */
18*76404edcSAsim Jamshed #include <rte_ip.h>
19*76404edcSAsim Jamshed #define ENABLE_STATS_IOCTL		1
20*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
21*76404edcSAsim Jamshed /* for close */
22*76404edcSAsim Jamshed #include <unistd.h>
23*76404edcSAsim Jamshed /* for open */
24*76404edcSAsim Jamshed #include <fcntl.h>
25*76404edcSAsim Jamshed /* for ioctl */
26*76404edcSAsim Jamshed #include <sys/ioctl.h>
27*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
28*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
29*76404edcSAsim Jamshed /* Essential macros */
30*76404edcSAsim Jamshed #define MAX_RX_QUEUE_PER_LCORE		MAX_CPUS
31*76404edcSAsim Jamshed #define MAX_TX_QUEUE_PER_PORT		MAX_CPUS
32*76404edcSAsim Jamshed 
33*76404edcSAsim Jamshed #define MBUF_SIZE 			(2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
34*76404edcSAsim Jamshed #define NB_MBUF				8192
35*76404edcSAsim Jamshed #define MEMPOOL_CACHE_SIZE		256
36*76404edcSAsim Jamshed 
37*76404edcSAsim Jamshed /*
38*76404edcSAsim Jamshed  * RX and TX Prefetch, Host, and Write-back threshold values should be
39*76404edcSAsim Jamshed  * carefully set for optimal performance. Consult the network
40*76404edcSAsim Jamshed  * controller's datasheet and supporting DPDK documentation for guidance
41*76404edcSAsim Jamshed  * on how these parameters should be set.
42*76404edcSAsim Jamshed  */
43*76404edcSAsim Jamshed #define RX_PTHRESH 			8 /**< Default values of RX prefetch threshold reg. */
44*76404edcSAsim Jamshed #define RX_HTHRESH 			8 /**< Default values of RX host threshold reg. */
45*76404edcSAsim Jamshed #define RX_WTHRESH 			4 /**< Default values of RX write-back threshold reg. */
46*76404edcSAsim Jamshed 
47*76404edcSAsim Jamshed /*
48*76404edcSAsim Jamshed  * These default values are optimized for use with the Intel(R) 82599 10 GbE
49*76404edcSAsim Jamshed  * Controller and the DPDK ixgbe PMD. Consider using other values for other
50*76404edcSAsim Jamshed  * network controllers and/or network drivers.
51*76404edcSAsim Jamshed  */
52*76404edcSAsim Jamshed #define TX_PTHRESH 			36 /**< Default values of TX prefetch threshold reg. */
53*76404edcSAsim Jamshed #define TX_HTHRESH			0  /**< Default values of TX host threshold reg. */
54*76404edcSAsim Jamshed #define TX_WTHRESH			0  /**< Default values of TX write-back threshold reg. */
55*76404edcSAsim Jamshed 
56*76404edcSAsim Jamshed #define MAX_PKT_BURST			/*32*/64/*128*//*32*/
57*76404edcSAsim Jamshed 
58*76404edcSAsim Jamshed /*
59*76404edcSAsim Jamshed  * Configurable number of RX/TX ring descriptors
60*76404edcSAsim Jamshed  */
61*76404edcSAsim Jamshed #define RTE_TEST_RX_DESC_DEFAULT	128
62*76404edcSAsim Jamshed #define RTE_TEST_TX_DESC_DEFAULT	512
63*76404edcSAsim Jamshed 
64*76404edcSAsim Jamshed static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
65*76404edcSAsim Jamshed static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
66*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
67*76404edcSAsim Jamshed /* packet memory pools for storing packet bufs */
68*76404edcSAsim Jamshed static struct rte_mempool *pktmbuf_pool[MAX_CPUS] = {NULL};
69*76404edcSAsim Jamshed static uint8_t cpu_qid_map[RTE_MAX_ETHPORTS][MAX_CPUS] = {{0}};
70*76404edcSAsim Jamshed 
71*76404edcSAsim Jamshed //#define DEBUG				1
72*76404edcSAsim Jamshed #ifdef DEBUG
73*76404edcSAsim Jamshed /* ethernet addresses of ports */
74*76404edcSAsim Jamshed static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
75*76404edcSAsim Jamshed #endif
76*76404edcSAsim Jamshed 
77*76404edcSAsim Jamshed static struct rte_eth_conf port_conf = {
78*76404edcSAsim Jamshed 	.rxmode = {
79*76404edcSAsim Jamshed 		.mq_mode	= 	ETH_MQ_RX_RSS,
80*76404edcSAsim Jamshed 		.max_rx_pkt_len = 	ETHER_MAX_LEN,
81*76404edcSAsim Jamshed 		.split_hdr_size = 	0,
82*76404edcSAsim Jamshed 		.header_split   = 	0, /**< Header Split disabled */
83*76404edcSAsim Jamshed 		.hw_ip_checksum = 	1, /**< IP checksum offload enabled */
84*76404edcSAsim Jamshed 		.hw_vlan_filter = 	0, /**< VLAN filtering disabled */
85*76404edcSAsim Jamshed 		.jumbo_frame    = 	0, /**< Jumbo Frame Support disabled */
86*76404edcSAsim Jamshed 		.hw_strip_crc   = 	1, /**< CRC stripped by hardware */
87*76404edcSAsim Jamshed 	},
88*76404edcSAsim Jamshed 	.rx_adv_conf = {
89*76404edcSAsim Jamshed 		.rss_conf = {
90*76404edcSAsim Jamshed 			.rss_key = 	NULL,
91*76404edcSAsim Jamshed 			.rss_hf = 	ETH_RSS_TCP
92*76404edcSAsim Jamshed 		},
93*76404edcSAsim Jamshed 	},
94*76404edcSAsim Jamshed 	.txmode = {
95*76404edcSAsim Jamshed 		.mq_mode = 		ETH_MQ_TX_NONE,
96*76404edcSAsim Jamshed 	},
97*76404edcSAsim Jamshed #if 0
98*76404edcSAsim Jamshed 	.fdir_conf = {
99*76404edcSAsim Jamshed                 .mode = RTE_FDIR_MODE_PERFECT,
100*76404edcSAsim Jamshed                 .pballoc = RTE_FDIR_PBALLOC_256K,
101*76404edcSAsim Jamshed                 .status = RTE_FDIR_REPORT_STATUS_ALWAYS,
102*76404edcSAsim Jamshed                 //.flexbytes_offset = 0x6,
103*76404edcSAsim Jamshed                 .drop_queue = 127,
104*76404edcSAsim Jamshed         },
105*76404edcSAsim Jamshed #endif
106*76404edcSAsim Jamshed };
107*76404edcSAsim Jamshed 
108*76404edcSAsim Jamshed static const struct rte_eth_rxconf rx_conf = {
109*76404edcSAsim Jamshed 	.rx_thresh = {
110*76404edcSAsim Jamshed 		.pthresh = 		RX_PTHRESH, /* RX prefetch threshold reg */
111*76404edcSAsim Jamshed 		.hthresh = 		RX_HTHRESH, /* RX host threshold reg */
112*76404edcSAsim Jamshed 		.wthresh = 		RX_WTHRESH, /* RX write-back threshold reg */
113*76404edcSAsim Jamshed 	},
114*76404edcSAsim Jamshed 	.rx_free_thresh = 		32,
115*76404edcSAsim Jamshed };
116*76404edcSAsim Jamshed 
117*76404edcSAsim Jamshed static const struct rte_eth_txconf tx_conf = {
118*76404edcSAsim Jamshed 	.tx_thresh = {
119*76404edcSAsim Jamshed 		.pthresh = 		TX_PTHRESH, /* TX prefetch threshold reg */
120*76404edcSAsim Jamshed 		.hthresh = 		TX_HTHRESH, /* TX host threshold reg */
121*76404edcSAsim Jamshed 		.wthresh = 		TX_WTHRESH, /* TX write-back threshold reg */
122*76404edcSAsim Jamshed 	},
123*76404edcSAsim Jamshed 	.tx_free_thresh = 		0, /* Use PMD default values */
124*76404edcSAsim Jamshed 	.tx_rs_thresh = 		0, /* Use PMD default values */
125*76404edcSAsim Jamshed 	/*
126*76404edcSAsim Jamshed 	 * As the example won't handle mult-segments and offload cases,
127*76404edcSAsim Jamshed 	 * set the flag by default.
128*76404edcSAsim Jamshed 	 */
129*76404edcSAsim Jamshed 	.txq_flags = 			0x0,
130*76404edcSAsim Jamshed };
131*76404edcSAsim Jamshed 
132*76404edcSAsim Jamshed struct mbuf_table {
133*76404edcSAsim Jamshed 	unsigned len; /* length of queued packets */
134*76404edcSAsim Jamshed 	struct rte_mbuf *m_table[MAX_PKT_BURST];
135*76404edcSAsim Jamshed };
136*76404edcSAsim Jamshed 
137*76404edcSAsim Jamshed struct dpdk_private_context {
138*76404edcSAsim Jamshed 	struct mbuf_table rmbufs[RTE_MAX_ETHPORTS];
139*76404edcSAsim Jamshed 	struct mbuf_table wmbufs[RTE_MAX_ETHPORTS];
140*76404edcSAsim Jamshed 	struct rte_mempool *pktmbuf_pool;
141*76404edcSAsim Jamshed 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
142*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
143*76404edcSAsim Jamshed 	int fd;
144*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
145*76404edcSAsim Jamshed } __rte_cache_aligned;
146*76404edcSAsim Jamshed 
147*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
148*76404edcSAsim Jamshed /**
149*76404edcSAsim Jamshed  * stats struct passed on from user space to the driver
150*76404edcSAsim Jamshed  */
151*76404edcSAsim Jamshed struct stats_struct {
152*76404edcSAsim Jamshed 	uint64_t tx_bytes;
153*76404edcSAsim Jamshed 	uint64_t tx_pkts;
154*76404edcSAsim Jamshed 	uint64_t rx_bytes;
155*76404edcSAsim Jamshed 	uint64_t rx_pkts;
156*76404edcSAsim Jamshed 	uint8_t qid;
157*76404edcSAsim Jamshed 	uint8_t dev;
158*76404edcSAsim Jamshed };
159*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
160*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
161*76404edcSAsim Jamshed void
162*76404edcSAsim Jamshed dpdk_init_handle(struct mtcp_thread_context *ctxt)
163*76404edcSAsim Jamshed {
164*76404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
165*76404edcSAsim Jamshed 	int i, j;
166*76404edcSAsim Jamshed 	char mempool_name[20];
167*76404edcSAsim Jamshed 
168*76404edcSAsim Jamshed 	/* create and initialize private I/O module context */
169*76404edcSAsim Jamshed 	ctxt->io_private_context = calloc(1, sizeof(struct dpdk_private_context));
170*76404edcSAsim Jamshed 	if (ctxt->io_private_context == NULL) {
171*76404edcSAsim Jamshed 		TRACE_ERROR("Failed to initialize ctxt->io_private_context: "
172*76404edcSAsim Jamshed 			    "Can't allocate memory\n");
173*76404edcSAsim Jamshed 		exit(EXIT_FAILURE);
174*76404edcSAsim Jamshed 	}
175*76404edcSAsim Jamshed 
176*76404edcSAsim Jamshed 	sprintf(mempool_name, "mbuf_pool-%d", ctxt->cpu);
177*76404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *)ctxt->io_private_context;
178*76404edcSAsim Jamshed 	dpc->pktmbuf_pool = pktmbuf_pool[ctxt->cpu];
179*76404edcSAsim Jamshed 
180*76404edcSAsim Jamshed 	/* set wmbufs correctly */
181*76404edcSAsim Jamshed 	for (j = 0; j < g_config.mos->netdev_table->num; j++) {
182*76404edcSAsim Jamshed 		/* Allocate wmbufs for each registered port */
183*76404edcSAsim Jamshed 		for (i = 0; i < MAX_PKT_BURST; i++) {
184*76404edcSAsim Jamshed 			dpc->wmbufs[j].m_table[i] = rte_pktmbuf_alloc(pktmbuf_pool[ctxt->cpu]);
185*76404edcSAsim Jamshed 			if (dpc->wmbufs[j].m_table[i] == NULL) {
186*76404edcSAsim Jamshed 				TRACE_ERROR("Failed to allocate %d:wmbuf[%d] on device %d!\n",
187*76404edcSAsim Jamshed 					    ctxt->cpu, i, j);
188*76404edcSAsim Jamshed 				exit(EXIT_FAILURE);
189*76404edcSAsim Jamshed 			}
190*76404edcSAsim Jamshed 		}
191*76404edcSAsim Jamshed 		/* set mbufs queue length to 0 to begin with */
192*76404edcSAsim Jamshed 		dpc->wmbufs[j].len = 0;
193*76404edcSAsim Jamshed 	}
194*76404edcSAsim Jamshed 
195*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
196*76404edcSAsim Jamshed 	dpc->fd = open("/dev/dpdk-iface", O_RDWR);
197*76404edcSAsim Jamshed 	if (dpc->fd == -1) {
198*76404edcSAsim Jamshed 		TRACE_ERROR("Can't open /dev/dpdk-iface for context->cpu: %d!\n",
199*76404edcSAsim Jamshed 			    ctxt->cpu);
200*76404edcSAsim Jamshed 		exit(EXIT_FAILURE);
201*76404edcSAsim Jamshed 	}
202*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
203*76404edcSAsim Jamshed }
204*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
205*76404edcSAsim Jamshed int
206*76404edcSAsim Jamshed dpdk_send_pkts(struct mtcp_thread_context *ctxt, int nif)
207*76404edcSAsim Jamshed {
208*76404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
209*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
210*76404edcSAsim Jamshed 	int ret;
211*76404edcSAsim Jamshed 	int qid;
212*76404edcSAsim Jamshed 
213*76404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *)ctxt->io_private_context;
214*76404edcSAsim Jamshed 	mtcp = ctxt->mtcp_manager;
215*76404edcSAsim Jamshed 	ret = 0;
216*76404edcSAsim Jamshed 	qid = cpu_qid_map[nif][ctxt->cpu];
217*76404edcSAsim Jamshed 
218*76404edcSAsim Jamshed 	/* if queue is unassigned, skip it.. */
219*76404edcSAsim Jamshed 	if (unlikely(qid == 0xFF))
220*76404edcSAsim Jamshed 		return 0;
221*76404edcSAsim Jamshed 
222*76404edcSAsim Jamshed 	/* if there are packets in the queue... flush them out to the wire */
223*76404edcSAsim Jamshed 	if (dpc->wmbufs[nif].len >/*= MAX_PKT_BURST*/ 0) {
224*76404edcSAsim Jamshed 		struct rte_mbuf **pkts;
225*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
226*76404edcSAsim Jamshed 		struct stats_struct ss;
227*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
228*76404edcSAsim Jamshed 		int cnt = dpc->wmbufs[nif].len;
229*76404edcSAsim Jamshed 		pkts = dpc->wmbufs[nif].m_table;
230*76404edcSAsim Jamshed #ifdef NETSTAT
231*76404edcSAsim Jamshed 		mtcp->nstat.tx_packets[nif] += cnt;
232*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
233*76404edcSAsim Jamshed 		ss.tx_pkts = mtcp->nstat.tx_packets[nif];
234*76404edcSAsim Jamshed 		ss.tx_bytes = mtcp->nstat.tx_bytes[nif];
235*76404edcSAsim Jamshed 		ss.rx_pkts = mtcp->nstat.rx_packets[nif];
236*76404edcSAsim Jamshed 		ss.rx_bytes = mtcp->nstat.rx_bytes[nif];
237*76404edcSAsim Jamshed 		ss.qid = ctxt->cpu;
238*76404edcSAsim Jamshed 		ss.dev = nif;
239*76404edcSAsim Jamshed 		ioctl(dpc->fd, 0, &ss);
240*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
241*76404edcSAsim Jamshed #endif
242*76404edcSAsim Jamshed 		do {
243*76404edcSAsim Jamshed 			/* tx cnt # of packets */
244*76404edcSAsim Jamshed 			ret = rte_eth_tx_burst(nif, qid,
245*76404edcSAsim Jamshed 					       pkts, cnt);
246*76404edcSAsim Jamshed 			pkts += ret;
247*76404edcSAsim Jamshed 			cnt -= ret;
248*76404edcSAsim Jamshed 			/* if not all pkts were sent... then repeat the cycle */
249*76404edcSAsim Jamshed 		} while (cnt > 0);
250*76404edcSAsim Jamshed 
251*76404edcSAsim Jamshed #ifndef SHARE_IO_BUFFER
252*76404edcSAsim Jamshed 		int i;
253*76404edcSAsim Jamshed 		/* time to allocate fresh mbufs for the queue */
254*76404edcSAsim Jamshed 		for (i = 0; i < dpc->wmbufs[nif].len; i++) {
255*76404edcSAsim Jamshed 			dpc->wmbufs[nif].m_table[i] = rte_pktmbuf_alloc(pktmbuf_pool[ctxt->cpu]);
256*76404edcSAsim Jamshed 			/* error checking */
257*76404edcSAsim Jamshed 			if (unlikely(dpc->wmbufs[nif].m_table[i] == NULL)) {
258*76404edcSAsim Jamshed 				TRACE_ERROR("Failed to allocate %d:wmbuf[%d] on device %d!\n",
259*76404edcSAsim Jamshed 					    ctxt->cpu, i, nif);
260*76404edcSAsim Jamshed 				exit(EXIT_FAILURE);
261*76404edcSAsim Jamshed 			}
262*76404edcSAsim Jamshed 		}
263*76404edcSAsim Jamshed #endif
264*76404edcSAsim Jamshed 		/* reset the len of mbufs var after flushing of packets */
265*76404edcSAsim Jamshed 		dpc->wmbufs[nif].len = 0;
266*76404edcSAsim Jamshed 	}
267*76404edcSAsim Jamshed 
268*76404edcSAsim Jamshed 	return ret;
269*76404edcSAsim Jamshed }
270*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
271*76404edcSAsim Jamshed uint8_t *
272*76404edcSAsim Jamshed dpdk_get_wptr(struct mtcp_thread_context *ctxt, int nif, uint16_t pktsize)
273*76404edcSAsim Jamshed {
274*76404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
275*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
276*76404edcSAsim Jamshed 	struct rte_mbuf *m;
277*76404edcSAsim Jamshed 	uint8_t *ptr;
278*76404edcSAsim Jamshed 	int len_of_mbuf;
279*76404edcSAsim Jamshed 
280*76404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
281*76404edcSAsim Jamshed 	mtcp = ctxt->mtcp_manager;
282*76404edcSAsim Jamshed 
283*76404edcSAsim Jamshed 	/* sanity check */
284*76404edcSAsim Jamshed 	if (unlikely(dpc->wmbufs[nif].len == MAX_PKT_BURST))
285*76404edcSAsim Jamshed 		return NULL;
286*76404edcSAsim Jamshed 
287*76404edcSAsim Jamshed 	len_of_mbuf = dpc->wmbufs[nif].len;
288*76404edcSAsim Jamshed 	m = dpc->wmbufs[nif].m_table[len_of_mbuf];
289*76404edcSAsim Jamshed 
290*76404edcSAsim Jamshed 	/* retrieve the right write offset */
291*76404edcSAsim Jamshed 	ptr = (void *)rte_pktmbuf_mtod(m, struct ether_hdr *);
292*76404edcSAsim Jamshed 	m->pkt_len = m->data_len = pktsize;
293*76404edcSAsim Jamshed 	m->nb_segs = 1;
294*76404edcSAsim Jamshed 	m->next = NULL;
295*76404edcSAsim Jamshed 
296*76404edcSAsim Jamshed #ifdef NETSTAT
297*76404edcSAsim Jamshed 	mtcp->nstat.tx_bytes[nif] += pktsize + 24;
298*76404edcSAsim Jamshed #endif
299*76404edcSAsim Jamshed 
300*76404edcSAsim Jamshed 	/* increment the len_of_mbuf var */
301*76404edcSAsim Jamshed 	dpc->wmbufs[nif].len = len_of_mbuf + 1;
302*76404edcSAsim Jamshed 
303*76404edcSAsim Jamshed 	return (uint8_t *)ptr;
304*76404edcSAsim Jamshed }
305*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
306*76404edcSAsim Jamshed void
307*76404edcSAsim Jamshed dpdk_set_wptr(struct mtcp_thread_context *ctxt, int out_nif, int in_nif, int index)
308*76404edcSAsim Jamshed {
309*76404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
310*76404edcSAsim Jamshed 	mtcp_manager_t mtcp;
311*76404edcSAsim Jamshed 	int len_of_mbuf;
312*76404edcSAsim Jamshed 
313*76404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
314*76404edcSAsim Jamshed 	mtcp = ctxt->mtcp_manager;
315*76404edcSAsim Jamshed 
316*76404edcSAsim Jamshed 	/* sanity check */
317*76404edcSAsim Jamshed 	if (unlikely(dpc->wmbufs[out_nif].len == MAX_PKT_BURST))
318*76404edcSAsim Jamshed 		return;
319*76404edcSAsim Jamshed 
320*76404edcSAsim Jamshed 	len_of_mbuf = dpc->wmbufs[out_nif].len;
321*76404edcSAsim Jamshed 	dpc->wmbufs[out_nif].m_table[len_of_mbuf] =
322*76404edcSAsim Jamshed 		dpc->rmbufs[in_nif].m_table[index];
323*76404edcSAsim Jamshed 
324*76404edcSAsim Jamshed 	dpc->wmbufs[out_nif].m_table[len_of_mbuf]->udata64 = 0;
325*76404edcSAsim Jamshed 
326*76404edcSAsim Jamshed #ifdef NETSTAT
327*76404edcSAsim Jamshed 	mtcp->nstat.tx_bytes[out_nif] += dpc->rmbufs[in_nif].m_table[index]->pkt_len + 24;
328*76404edcSAsim Jamshed #endif
329*76404edcSAsim Jamshed 
330*76404edcSAsim Jamshed 	/* increment the len_of_mbuf var */
331*76404edcSAsim Jamshed 	dpc->wmbufs[out_nif].len = len_of_mbuf + 1;
332*76404edcSAsim Jamshed 
333*76404edcSAsim Jamshed 	return;
334*76404edcSAsim Jamshed }
335*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
336*76404edcSAsim Jamshed static inline void
337*76404edcSAsim Jamshed free_pkts(struct rte_mbuf **mtable, unsigned len)
338*76404edcSAsim Jamshed {
339*76404edcSAsim Jamshed 	int i;
340*76404edcSAsim Jamshed 
341*76404edcSAsim Jamshed 	/* free the freaking packets */
342*76404edcSAsim Jamshed 	for (i = 0; i < len; i++) {
343*76404edcSAsim Jamshed 		if (mtable[i]->udata64 == 1) {
344*76404edcSAsim Jamshed 			rte_pktmbuf_free_seg(mtable[i]);
345*76404edcSAsim Jamshed 			RTE_MBUF_PREFETCH_TO_FREE(mtable[i+1]);
346*76404edcSAsim Jamshed 		}
347*76404edcSAsim Jamshed 	}
348*76404edcSAsim Jamshed }
349*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
350*76404edcSAsim Jamshed int32_t
351*76404edcSAsim Jamshed dpdk_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx)
352*76404edcSAsim Jamshed {
353*76404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
354*76404edcSAsim Jamshed 	int ret;
355*76404edcSAsim Jamshed 	uint8_t qid;
356*76404edcSAsim Jamshed 
357*76404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
358*76404edcSAsim Jamshed 	qid = cpu_qid_map[ifidx][ctxt->cpu];
359*76404edcSAsim Jamshed 
360*76404edcSAsim Jamshed 	/* if queue is unassigned, skip it.. */
361*76404edcSAsim Jamshed 	if (qid == 0xFF)
362*76404edcSAsim Jamshed 		return 0;
363*76404edcSAsim Jamshed 
364*76404edcSAsim Jamshed 	if (dpc->rmbufs[ifidx].len != 0) {
365*76404edcSAsim Jamshed 		free_pkts(dpc->rmbufs[ifidx].m_table, dpc->rmbufs[ifidx].len);
366*76404edcSAsim Jamshed 		dpc->rmbufs[ifidx].len = 0;
367*76404edcSAsim Jamshed 	}
368*76404edcSAsim Jamshed 
369*76404edcSAsim Jamshed 	ret = rte_eth_rx_burst((uint8_t)ifidx, qid,
370*76404edcSAsim Jamshed 			       dpc->pkts_burst, MAX_PKT_BURST);
371*76404edcSAsim Jamshed 
372*76404edcSAsim Jamshed 	dpc->rmbufs[ifidx].len = ret;
373*76404edcSAsim Jamshed 
374*76404edcSAsim Jamshed 	return ret;
375*76404edcSAsim Jamshed }
376*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
377*76404edcSAsim Jamshed uint8_t *
378*76404edcSAsim Jamshed dpdk_get_rptr(struct mtcp_thread_context *ctxt, int ifidx, int index, uint16_t *len)
379*76404edcSAsim Jamshed {
380*76404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
381*76404edcSAsim Jamshed 	struct rte_mbuf *m;
382*76404edcSAsim Jamshed 	uint8_t *pktbuf;
383*76404edcSAsim Jamshed 
384*76404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
385*76404edcSAsim Jamshed 
386*76404edcSAsim Jamshed 
387*76404edcSAsim Jamshed 	m = dpc->pkts_burst[index];
388*76404edcSAsim Jamshed 	/* tag to check if the packet is a local or a forwarded pkt */
389*76404edcSAsim Jamshed 	m->udata64 = 1;
390*76404edcSAsim Jamshed 	/* don't enable pre-fetching... performance goes down */
391*76404edcSAsim Jamshed 	//rte_prefetch0(rte_pktmbuf_mtod(m, void *));
392*76404edcSAsim Jamshed 	*len = m->pkt_len;
393*76404edcSAsim Jamshed 	pktbuf = rte_pktmbuf_mtod(m, uint8_t *);
394*76404edcSAsim Jamshed 
395*76404edcSAsim Jamshed 	/* enqueue the pkt ptr in mbuf */
396*76404edcSAsim Jamshed 	dpc->rmbufs[ifidx].m_table[index] = m;
397*76404edcSAsim Jamshed 
398*76404edcSAsim Jamshed 	return pktbuf;
399*76404edcSAsim Jamshed }
400*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
401*76404edcSAsim Jamshed int
402*76404edcSAsim Jamshed dpdk_get_nif(struct ifreq *ifr)
403*76404edcSAsim Jamshed {
404*76404edcSAsim Jamshed 	int i;
405*76404edcSAsim Jamshed 	static int num_dev = -1;
406*76404edcSAsim Jamshed 	static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS];
407*76404edcSAsim Jamshed 	/* get mac addr entries of 'detected' dpdk ports */
408*76404edcSAsim Jamshed 	if (num_dev < 0) {
409*76404edcSAsim Jamshed 		num_dev = rte_eth_dev_count();
410*76404edcSAsim Jamshed 		for (i = 0; i < num_dev; i++)
411*76404edcSAsim Jamshed 			rte_eth_macaddr_get(i, &ports_eth_addr[i]);
412*76404edcSAsim Jamshed 	}
413*76404edcSAsim Jamshed 
414*76404edcSAsim Jamshed 	for (i = 0; i < num_dev; i++)
415*76404edcSAsim Jamshed 		if (!memcmp(&ifr->ifr_addr.sa_data[0], &ports_eth_addr[i], ETH_ALEN))
416*76404edcSAsim Jamshed 			return i;
417*76404edcSAsim Jamshed 
418*76404edcSAsim Jamshed 	return -1;
419*76404edcSAsim Jamshed }
420*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
421*76404edcSAsim Jamshed void
422*76404edcSAsim Jamshed dpdk_destroy_handle(struct mtcp_thread_context *ctxt)
423*76404edcSAsim Jamshed {
424*76404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
425*76404edcSAsim Jamshed 	int i;
426*76404edcSAsim Jamshed 
427*76404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *) ctxt->io_private_context;
428*76404edcSAsim Jamshed 
429*76404edcSAsim Jamshed 	/* free wmbufs */
430*76404edcSAsim Jamshed 	for (i = 0; i < g_config.mos->netdev_table->num; i++)
431*76404edcSAsim Jamshed 		free_pkts(dpc->wmbufs[i].m_table, MAX_PKT_BURST);
432*76404edcSAsim Jamshed 
433*76404edcSAsim Jamshed #ifdef ENABLE_STATS_IOCTL
434*76404edcSAsim Jamshed 	/* free fd */
435*76404edcSAsim Jamshed 	close(dpc->fd);
436*76404edcSAsim Jamshed #endif /* !ENABLE_STATS_IOCTL */
437*76404edcSAsim Jamshed 
438*76404edcSAsim Jamshed 	/* free it all up */
439*76404edcSAsim Jamshed 	free(dpc);
440*76404edcSAsim Jamshed }
441*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
442*76404edcSAsim Jamshed static void
443*76404edcSAsim Jamshed check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
444*76404edcSAsim Jamshed {
445*76404edcSAsim Jamshed #define CHECK_INTERVAL 			100 /* 100ms */
446*76404edcSAsim Jamshed #define MAX_CHECK_TIME 			90 /* 9s (90 * 100ms) in total */
447*76404edcSAsim Jamshed 
448*76404edcSAsim Jamshed 	uint8_t portid, count, all_ports_up, print_flag = 0;
449*76404edcSAsim Jamshed 	struct rte_eth_link link;
450*76404edcSAsim Jamshed 
451*76404edcSAsim Jamshed 	printf("\nChecking link status");
452*76404edcSAsim Jamshed 	fflush(stdout);
453*76404edcSAsim Jamshed 	for (count = 0; count <= MAX_CHECK_TIME; count++) {
454*76404edcSAsim Jamshed 		all_ports_up = 1;
455*76404edcSAsim Jamshed 		for (portid = 0; portid < port_num; portid++) {
456*76404edcSAsim Jamshed 			if ((port_mask & (1 << portid)) == 0)
457*76404edcSAsim Jamshed 				continue;
458*76404edcSAsim Jamshed 			memset(&link, 0, sizeof(link));
459*76404edcSAsim Jamshed 			rte_eth_link_get_nowait(portid, &link);
460*76404edcSAsim Jamshed 			/* print link status if flag set */
461*76404edcSAsim Jamshed 			if (print_flag == 1) {
462*76404edcSAsim Jamshed 				if (link.link_status)
463*76404edcSAsim Jamshed 					printf("Port %d Link Up - speed %u "
464*76404edcSAsim Jamshed 						"Mbps - %s\n", (uint8_t)portid,
465*76404edcSAsim Jamshed 						(unsigned)link.link_speed,
466*76404edcSAsim Jamshed 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
467*76404edcSAsim Jamshed 					("full-duplex") : ("half-duplex\n"));
468*76404edcSAsim Jamshed 				else
469*76404edcSAsim Jamshed 					printf("Port %d Link Down\n",
470*76404edcSAsim Jamshed 						(uint8_t)portid);
471*76404edcSAsim Jamshed 				continue;
472*76404edcSAsim Jamshed 			}
473*76404edcSAsim Jamshed 			/* clear all_ports_up flag if any link down */
474*76404edcSAsim Jamshed 			if (link.link_status == 0) {
475*76404edcSAsim Jamshed 				all_ports_up = 0;
476*76404edcSAsim Jamshed 				break;
477*76404edcSAsim Jamshed 			}
478*76404edcSAsim Jamshed 		}
479*76404edcSAsim Jamshed 		/* after finally printing all link status, get out */
480*76404edcSAsim Jamshed 		if (print_flag == 1)
481*76404edcSAsim Jamshed 			break;
482*76404edcSAsim Jamshed 
483*76404edcSAsim Jamshed 		if (all_ports_up == 0) {
484*76404edcSAsim Jamshed 			printf(".");
485*76404edcSAsim Jamshed 			fflush(stdout);
486*76404edcSAsim Jamshed 			rte_delay_ms(CHECK_INTERVAL);
487*76404edcSAsim Jamshed 		}
488*76404edcSAsim Jamshed 
489*76404edcSAsim Jamshed 		/* set the print_flag if all ports up or timeout */
490*76404edcSAsim Jamshed 		if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
491*76404edcSAsim Jamshed 			print_flag = 1;
492*76404edcSAsim Jamshed 			printf("done\n");
493*76404edcSAsim Jamshed 		}
494*76404edcSAsim Jamshed 	}
495*76404edcSAsim Jamshed }
496*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
497*76404edcSAsim Jamshed #if 0
498*76404edcSAsim Jamshed static void
499*76404edcSAsim Jamshed dpdk_enable_fdir(int portid, uint8_t is_master)
500*76404edcSAsim Jamshed {
501*76404edcSAsim Jamshed 	struct rte_fdir_masks fdir_masks;
502*76404edcSAsim Jamshed 	struct rte_fdir_filter fdir_filter;
503*76404edcSAsim Jamshed 	int ret;
504*76404edcSAsim Jamshed 
505*76404edcSAsim Jamshed 	memset(&fdir_filter, 0, sizeof(struct rte_fdir_filter));
506*76404edcSAsim Jamshed 	fdir_filter.iptype = RTE_FDIR_IPTYPE_IPV4;
507*76404edcSAsim Jamshed 	fdir_filter.l4type = RTE_FDIR_L4TYPE_TCP;
508*76404edcSAsim Jamshed 	fdir_filter.ip_dst.ipv4_addr = g_config.mos->netdev_table->ent[portid]->ip_addr;
509*76404edcSAsim Jamshed 
510*76404edcSAsim Jamshed 	if (is_master) {
511*76404edcSAsim Jamshed 		memset(&fdir_masks, 0, sizeof(struct rte_fdir_masks));
512*76404edcSAsim Jamshed 		fdir_masks.src_ipv4_mask = 0x0;
513*76404edcSAsim Jamshed 		fdir_masks.dst_ipv4_mask = 0xFFFFFFFF;
514*76404edcSAsim Jamshed 		fdir_masks.src_port_mask = 0x0;
515*76404edcSAsim Jamshed 		fdir_masks.dst_port_mask = 0x0;
516*76404edcSAsim Jamshed 
517*76404edcSAsim Jamshed 		/*
518*76404edcSAsim Jamshed 		 * enable the following if the filter is IP-only
519*76404edcSAsim Jamshed 		 * (non-TCP, non-UDP)
520*76404edcSAsim Jamshed 		 */
521*76404edcSAsim Jamshed 		/* fdir_masks.only_ip_flow = 1; */
522*76404edcSAsim Jamshed 		rte_eth_dev_fdir_set_masks(portid, &fdir_masks);
523*76404edcSAsim Jamshed 		ret = rte_eth_dev_fdir_add_perfect_filter(portid,
524*76404edcSAsim Jamshed 							  &fdir_filter,
525*76404edcSAsim Jamshed 							  0,
526*76404edcSAsim Jamshed 							  g_config.mos->multiprocess_curr_core,
527*76404edcSAsim Jamshed 							  0);
528*76404edcSAsim Jamshed 	} else {
529*76404edcSAsim Jamshed 		ret = rte_eth_dev_fdir_update_perfect_filter(portid,
530*76404edcSAsim Jamshed 							     &fdir_filter,
531*76404edcSAsim Jamshed 							     0,
532*76404edcSAsim Jamshed 							     g_config.mos->multiprocess_curr_core,
533*76404edcSAsim Jamshed 							     0);
534*76404edcSAsim Jamshed 	}
535*76404edcSAsim Jamshed 	if (ret < 0) {
536*76404edcSAsim Jamshed 		rte_exit(EXIT_FAILURE,
537*76404edcSAsim Jamshed 			 "fdir_add_perfect_filter_t call failed!: %d\n",
538*76404edcSAsim Jamshed 			 ret);
539*76404edcSAsim Jamshed 	}
540*76404edcSAsim Jamshed 	fprintf(stderr, "Filter for device ifidx: %d added\n", portid);
541*76404edcSAsim Jamshed }
542*76404edcSAsim Jamshed #endif
543*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
544*76404edcSAsim Jamshed int32_t
545*76404edcSAsim Jamshed dpdk_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp)
546*76404edcSAsim Jamshed {
547*76404edcSAsim Jamshed 	struct dpdk_private_context *dpc;
548*76404edcSAsim Jamshed 	struct rte_mbuf *m;
549*76404edcSAsim Jamshed 	int len_of_mbuf;
550*76404edcSAsim Jamshed 	struct iphdr *iph;
551*76404edcSAsim Jamshed 	struct tcphdr *tcph;
552*76404edcSAsim Jamshed 	RssInfo *rss_i;
553*76404edcSAsim Jamshed 
554*76404edcSAsim Jamshed 	iph = (struct iphdr *)argp;
555*76404edcSAsim Jamshed 	dpc = (struct dpdk_private_context *)ctx->io_private_context;
556*76404edcSAsim Jamshed 	len_of_mbuf = dpc->wmbufs[nif].len;
557*76404edcSAsim Jamshed 	rss_i = NULL;
558*76404edcSAsim Jamshed 
559*76404edcSAsim Jamshed 	switch (cmd) {
560*76404edcSAsim Jamshed 	case PKT_TX_IP_CSUM:
561*76404edcSAsim Jamshed 		m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1];
562*76404edcSAsim Jamshed 		m->ol_flags = PKT_TX_OUTER_IP_CKSUM |
563*76404edcSAsim Jamshed 			PKT_TX_IP_CKSUM | PKT_TX_IPV4;
564*76404edcSAsim Jamshed 		m->l2_len = sizeof(struct ether_hdr);
565*76404edcSAsim Jamshed 		m->l3_len = (iph->ihl<<2);
566*76404edcSAsim Jamshed 		break;
567*76404edcSAsim Jamshed 	case PKT_TX_TCP_CSUM:
568*76404edcSAsim Jamshed 		m = dpc->wmbufs[nif].m_table[len_of_mbuf - 1];
569*76404edcSAsim Jamshed 		tcph = (struct tcphdr *)((unsigned char *)iph + (iph->ihl<<2));
570*76404edcSAsim Jamshed 		m->ol_flags |= PKT_TX_TCP_CKSUM;
571*76404edcSAsim Jamshed 		tcph->check = rte_ipv4_phdr_cksum((struct ipv4_hdr *)iph, m->ol_flags);
572*76404edcSAsim Jamshed 		break;
573*76404edcSAsim Jamshed 	case PKT_RX_RSS:
574*76404edcSAsim Jamshed 		rss_i = (RssInfo *)argp;
575*76404edcSAsim Jamshed 		m = dpc->pkts_burst[rss_i->pktidx];
576*76404edcSAsim Jamshed 		rss_i->hash_value = m->hash.rss;
577*76404edcSAsim Jamshed 		break;
578*76404edcSAsim Jamshed 	default:
579*76404edcSAsim Jamshed 		goto dev_ioctl_err;
580*76404edcSAsim Jamshed 	}
581*76404edcSAsim Jamshed 
582*76404edcSAsim Jamshed 	return 0;
583*76404edcSAsim Jamshed  dev_ioctl_err:
584*76404edcSAsim Jamshed 	return -1;
585*76404edcSAsim Jamshed }
586*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
587*76404edcSAsim Jamshed void
588*76404edcSAsim Jamshed dpdk_load_module_upper_half(void)
589*76404edcSAsim Jamshed {
590*76404edcSAsim Jamshed 	int cpu = g_config.mos->num_cores, ret;
591*76404edcSAsim Jamshed 	uint32_t cpumask = 0;
592*76404edcSAsim Jamshed 	char cpumaskbuf[10];
593*76404edcSAsim Jamshed 	char mem_channels[5];
594*76404edcSAsim Jamshed 
595*76404edcSAsim Jamshed 	/* set the log level */
596*76404edcSAsim Jamshed 	rte_set_log_type(RTE_LOGTYPE_PMD, 0);
597*76404edcSAsim Jamshed 	rte_set_log_type(RTE_LOGTYPE_MALLOC, 0);
598*76404edcSAsim Jamshed 	rte_set_log_type(RTE_LOGTYPE_MEMPOOL, 0);
599*76404edcSAsim Jamshed 	rte_set_log_type(RTE_LOGTYPE_RING, 0);
600*76404edcSAsim Jamshed 	rte_set_log_level(RTE_LOG_WARNING);
601*76404edcSAsim Jamshed 
602*76404edcSAsim Jamshed 	/* get the cpu mask */
603*76404edcSAsim Jamshed 	for (ret = 0; ret < cpu; ret++)
604*76404edcSAsim Jamshed 		cpumask = (cpumask | (1 << ret));
605*76404edcSAsim Jamshed 	sprintf(cpumaskbuf, "%X", cpumask);
606*76404edcSAsim Jamshed 
607*76404edcSAsim Jamshed 	/* get the mem channels per socket */
608*76404edcSAsim Jamshed 	if (g_config.mos->nb_mem_channels == 0) {
609*76404edcSAsim Jamshed 		TRACE_ERROR("DPDK module requires # of memory channels "
610*76404edcSAsim Jamshed 				"per socket parameter!\n");
611*76404edcSAsim Jamshed 		exit(EXIT_FAILURE);
612*76404edcSAsim Jamshed 	}
613*76404edcSAsim Jamshed 	sprintf(mem_channels, "%d", g_config.mos->nb_mem_channels);
614*76404edcSAsim Jamshed 
615*76404edcSAsim Jamshed 	/* initialize the rte env first, what a waste of implementation effort!  */
616*76404edcSAsim Jamshed 	char *argv[] = {"",
617*76404edcSAsim Jamshed 			"-c",
618*76404edcSAsim Jamshed 			cpumaskbuf,
619*76404edcSAsim Jamshed 			"-n",
620*76404edcSAsim Jamshed 			mem_channels,
621*76404edcSAsim Jamshed 			"--proc-type=auto",
622*76404edcSAsim Jamshed 			""
623*76404edcSAsim Jamshed 	};
624*76404edcSAsim Jamshed 	const int argc = 6;
625*76404edcSAsim Jamshed 
626*76404edcSAsim Jamshed 	/*
627*76404edcSAsim Jamshed 	 * re-set getopt extern variable optind.
628*76404edcSAsim Jamshed 	 * this issue was a bitch to debug
629*76404edcSAsim Jamshed 	 * rte_eal_init() internally uses getopt() syscall
630*76404edcSAsim Jamshed 	 * mtcp applications that also use an `external' getopt
631*76404edcSAsim Jamshed 	 * will cause a violent crash if optind is not reset to zero
632*76404edcSAsim Jamshed 	 * prior to calling the func below...
633*76404edcSAsim Jamshed 	 * see man getopt(3) for more details
634*76404edcSAsim Jamshed 	 */
635*76404edcSAsim Jamshed 	optind = 0;
636*76404edcSAsim Jamshed 
637*76404edcSAsim Jamshed 	/* initialize the dpdk eal env */
638*76404edcSAsim Jamshed 	ret = rte_eal_init(argc, argv);
639*76404edcSAsim Jamshed 	if (ret < 0)
640*76404edcSAsim Jamshed 		rte_exit(EXIT_FAILURE, "Invalid EAL args!\n");
641*76404edcSAsim Jamshed 
642*76404edcSAsim Jamshed }
643*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
644*76404edcSAsim Jamshed void
645*76404edcSAsim Jamshed dpdk_load_module_lower_half(void)
646*76404edcSAsim Jamshed {
647*76404edcSAsim Jamshed 	int portid, rxlcore_id, ret;
648*76404edcSAsim Jamshed 	struct rte_eth_fc_conf fc_conf;	/* for Ethernet flow control settings */
649*76404edcSAsim Jamshed 	/* setting the rss key */
650*76404edcSAsim Jamshed 	static const uint8_t key[] = {
651*76404edcSAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
652*76404edcSAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
653*76404edcSAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
654*76404edcSAsim Jamshed 		0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
655*76404edcSAsim Jamshed 	};
656*76404edcSAsim Jamshed 
657*76404edcSAsim Jamshed 	port_conf.rx_adv_conf.rss_conf.rss_key = (uint8_t *)&key;
658*76404edcSAsim Jamshed 	port_conf.rx_adv_conf.rss_conf.rss_key_len = sizeof(key);
659*76404edcSAsim Jamshed 
660*76404edcSAsim Jamshed 	/* resetting cpu_qid mapping */
661*76404edcSAsim Jamshed 	memset(cpu_qid_map, 0xFF, sizeof(cpu_qid_map));
662*76404edcSAsim Jamshed 
663*76404edcSAsim Jamshed 	if (!g_config.mos->multiprocess
664*76404edcSAsim Jamshed 			|| (g_config.mos->multiprocess && g_config.mos->multiprocess_is_master)) {
665*76404edcSAsim Jamshed 		for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) {
666*76404edcSAsim Jamshed 			char name[20];
667*76404edcSAsim Jamshed 			sprintf(name, "mbuf_pool-%d", rxlcore_id);
668*76404edcSAsim Jamshed 			/* create the mbuf pools */
669*76404edcSAsim Jamshed 			pktmbuf_pool[rxlcore_id] =
670*76404edcSAsim Jamshed 				rte_mempool_create(name, NB_MBUF,
671*76404edcSAsim Jamshed 						   MBUF_SIZE, MEMPOOL_CACHE_SIZE,
672*76404edcSAsim Jamshed 						   sizeof(struct rte_pktmbuf_pool_private),
673*76404edcSAsim Jamshed 						   rte_pktmbuf_pool_init, NULL,
674*76404edcSAsim Jamshed 						   rte_pktmbuf_init, NULL,
675*76404edcSAsim Jamshed 						   rte_lcore_to_socket_id(rxlcore_id), 0);
676*76404edcSAsim Jamshed 			if (pktmbuf_pool[rxlcore_id] == NULL)
677*76404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
678*76404edcSAsim Jamshed 		}
679*76404edcSAsim Jamshed 
680*76404edcSAsim Jamshed 		/* Initialise each port */
681*76404edcSAsim Jamshed 		for (portid = 0; portid < g_config.mos->netdev_table->num; portid++) {
682*76404edcSAsim Jamshed 			int num_queue = 0, eth_idx, i, queue_id;
683*76404edcSAsim Jamshed 			for (eth_idx = 0; eth_idx < g_config.mos->netdev_table->num; eth_idx++)
684*76404edcSAsim Jamshed 				if (portid == g_config.mos->netdev_table->ent[eth_idx]->ifindex)
685*76404edcSAsim Jamshed 					break;
686*76404edcSAsim Jamshed 			if (eth_idx == g_config.mos->netdev_table->num)
687*76404edcSAsim Jamshed 				continue;
688*76404edcSAsim Jamshed 			for (i = 0; i < sizeof(uint64_t) * 8; i++)
689*76404edcSAsim Jamshed 				if (g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << i))
690*76404edcSAsim Jamshed 					num_queue++;
691*76404edcSAsim Jamshed 
692*76404edcSAsim Jamshed 			/* set 'num_queues' (used for GetRSSCPUCore() in util.c) */
693*76404edcSAsim Jamshed 			num_queues = num_queue;
694*76404edcSAsim Jamshed 
695*76404edcSAsim Jamshed 			/* init port */
696*76404edcSAsim Jamshed 			printf("Initializing port %u... ", (unsigned) portid);
697*76404edcSAsim Jamshed 			fflush(stdout);
698*76404edcSAsim Jamshed 			ret = rte_eth_dev_configure(portid, num_queue, num_queue,
699*76404edcSAsim Jamshed 										&port_conf);
700*76404edcSAsim Jamshed 			if (ret < 0)
701*76404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Cannot configure device:"
702*76404edcSAsim Jamshed 									   "err=%d, port=%u\n",
703*76404edcSAsim Jamshed 									   ret, (unsigned) portid);
704*76404edcSAsim Jamshed 
705*76404edcSAsim Jamshed 			/* init one RX queue per CPU */
706*76404edcSAsim Jamshed 			fflush(stdout);
707*76404edcSAsim Jamshed #ifdef DEBUG
708*76404edcSAsim Jamshed 			rte_eth_macaddr_get(portid, &ports_eth_addr[portid]);
709*76404edcSAsim Jamshed #endif
710*76404edcSAsim Jamshed 			queue_id = 0;
711*76404edcSAsim Jamshed 			for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) {
712*76404edcSAsim Jamshed 				if (!(g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << rxlcore_id)))
713*76404edcSAsim Jamshed 					continue;
714*76404edcSAsim Jamshed 				ret = rte_eth_rx_queue_setup(portid, queue_id, nb_rxd,
715*76404edcSAsim Jamshed 						rte_eth_dev_socket_id(portid), &rx_conf,
716*76404edcSAsim Jamshed 						pktmbuf_pool[rxlcore_id]);
717*76404edcSAsim Jamshed 				if (ret < 0)
718*76404edcSAsim Jamshed 					rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:"
719*76404edcSAsim Jamshed 										   "err=%d, port=%u, queueid: %d\n",
720*76404edcSAsim Jamshed 										   ret, (unsigned) portid, rxlcore_id);
721*76404edcSAsim Jamshed 				cpu_qid_map[portid][rxlcore_id] = queue_id++;
722*76404edcSAsim Jamshed 			}
723*76404edcSAsim Jamshed 
724*76404edcSAsim Jamshed 			/* init one TX queue on each port per CPU (this is redundant for
725*76404edcSAsim Jamshed 			 * this app) */
726*76404edcSAsim Jamshed 			fflush(stdout);
727*76404edcSAsim Jamshed 			queue_id = 0;
728*76404edcSAsim Jamshed 			for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) {
729*76404edcSAsim Jamshed 				if (!(g_config.mos->netdev_table->ent[eth_idx]->cpu_mask & (1L << rxlcore_id)))
730*76404edcSAsim Jamshed 					continue;
731*76404edcSAsim Jamshed 				ret = rte_eth_tx_queue_setup(portid, queue_id++, nb_txd,
732*76404edcSAsim Jamshed 						rte_eth_dev_socket_id(portid), &tx_conf);
733*76404edcSAsim Jamshed 				if (ret < 0)
734*76404edcSAsim Jamshed 					rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:"
735*76404edcSAsim Jamshed 										   "err=%d, port=%u, queueid: %d\n",
736*76404edcSAsim Jamshed 										   ret, (unsigned) portid, rxlcore_id);
737*76404edcSAsim Jamshed 			}
738*76404edcSAsim Jamshed 
739*76404edcSAsim Jamshed 			/* Start device */
740*76404edcSAsim Jamshed 			ret = rte_eth_dev_start(portid);
741*76404edcSAsim Jamshed 			if (ret < 0)
742*76404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n",
743*76404edcSAsim Jamshed 									   ret, (unsigned) portid);
744*76404edcSAsim Jamshed 
745*76404edcSAsim Jamshed 			printf("done: \n");
746*76404edcSAsim Jamshed 			rte_eth_promiscuous_enable(portid);
747*76404edcSAsim Jamshed 
748*76404edcSAsim Jamshed 			/* retrieve current flow control settings per port */
749*76404edcSAsim Jamshed 			memset(&fc_conf, 0, sizeof(fc_conf));
750*76404edcSAsim Jamshed 			ret = rte_eth_dev_flow_ctrl_get(portid, &fc_conf);
751*76404edcSAsim Jamshed 			if (ret != 0) {
752*76404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Failed to get flow control info!\n");
753*76404edcSAsim Jamshed 			}
754*76404edcSAsim Jamshed 
755*76404edcSAsim Jamshed 			/* and just disable the rx/tx flow control */
756*76404edcSAsim Jamshed 			fc_conf.mode = RTE_FC_NONE;
757*76404edcSAsim Jamshed 			ret = rte_eth_dev_flow_ctrl_set(portid, &fc_conf);
758*76404edcSAsim Jamshed 			if (ret != 0) {
759*76404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Failed to set flow control info!: errno: %d\n",
760*76404edcSAsim Jamshed 					 ret);
761*76404edcSAsim Jamshed 			}
762*76404edcSAsim Jamshed 
763*76404edcSAsim Jamshed #ifdef DEBUG
764*76404edcSAsim Jamshed 			printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
765*76404edcSAsim Jamshed 					(unsigned) portid,
766*76404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[0],
767*76404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[1],
768*76404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[2],
769*76404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[3],
770*76404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[4],
771*76404edcSAsim Jamshed 					ports_eth_addr[portid].addr_bytes[5]);
772*76404edcSAsim Jamshed #endif
773*76404edcSAsim Jamshed #if 0
774*76404edcSAsim Jamshed 			/* if multi-process support is enabled, then turn on FDIR */
775*76404edcSAsim Jamshed 			if (g_config.mos->multiprocess)
776*76404edcSAsim Jamshed 				dpdk_enable_fdir(portid, g_config.mos->multiprocess_is_master);
777*76404edcSAsim Jamshed #endif
778*76404edcSAsim Jamshed 		}
779*76404edcSAsim Jamshed 	} else { /* g_config.mos->multiprocess && !g_config.mos->multiprocess_is_master */
780*76404edcSAsim Jamshed 		for (rxlcore_id = 0; rxlcore_id < g_config.mos->num_cores; rxlcore_id++) {
781*76404edcSAsim Jamshed 			char name[20];
782*76404edcSAsim Jamshed 			sprintf(name, "mbuf_pool-%d", rxlcore_id);
783*76404edcSAsim Jamshed 			/* initialize the mbuf pools */
784*76404edcSAsim Jamshed 			pktmbuf_pool[rxlcore_id] =
785*76404edcSAsim Jamshed 				rte_mempool_lookup(name);
786*76404edcSAsim Jamshed 			if (pktmbuf_pool[rxlcore_id] == NULL)
787*76404edcSAsim Jamshed 				rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
788*76404edcSAsim Jamshed 		}
789*76404edcSAsim Jamshed #if 0
790*76404edcSAsim Jamshed 		for (portid = 0; portid < g_config.mos->netdev_table->num; portid++)
791*76404edcSAsim Jamshed 			dpdk_enable_fdir(portid, g_config.mos->multiprocess_is_master);
792*76404edcSAsim Jamshed #endif
793*76404edcSAsim Jamshed 	}
794*76404edcSAsim Jamshed 
795*76404edcSAsim Jamshed 	check_all_ports_link_status(g_config.mos->netdev_table->num, 0xFFFFFFFF);
796*76404edcSAsim Jamshed }
797*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
798*76404edcSAsim Jamshed io_module_func dpdk_module_func = {
799*76404edcSAsim Jamshed 	.load_module_upper_half		   = dpdk_load_module_upper_half,
800*76404edcSAsim Jamshed 	.load_module_lower_half		   = dpdk_load_module_lower_half,
801*76404edcSAsim Jamshed 	.init_handle		   = dpdk_init_handle,
802*76404edcSAsim Jamshed 	.link_devices		   = NULL,
803*76404edcSAsim Jamshed 	.release_pkt		   = NULL,
804*76404edcSAsim Jamshed 	.send_pkts		   = dpdk_send_pkts,
805*76404edcSAsim Jamshed 	.get_wptr   		   = dpdk_get_wptr,
806*76404edcSAsim Jamshed 	.recv_pkts		   = dpdk_recv_pkts,
807*76404edcSAsim Jamshed 	.get_rptr	   	   = dpdk_get_rptr,
808*76404edcSAsim Jamshed 	.get_nif		   = dpdk_get_nif,
809*76404edcSAsim Jamshed 	.select			   = NULL,
810*76404edcSAsim Jamshed 	.destroy_handle		   = dpdk_destroy_handle,
811*76404edcSAsim Jamshed 	.dev_ioctl		   = dpdk_dev_ioctl,
812*76404edcSAsim Jamshed 	.set_wptr		   = dpdk_set_wptr,
813*76404edcSAsim Jamshed };
814*76404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
815*76404edcSAsim Jamshed 
816