1522d5c66SAsim Jamshed /* for io_module_func def'ns */
2522d5c66SAsim Jamshed #include "io_module.h"
3522d5c66SAsim Jamshed /* for mtcp related def'ns */
4522d5c66SAsim Jamshed #include "mtcp.h"
5522d5c66SAsim Jamshed /* for errno */
6522d5c66SAsim Jamshed #include <errno.h>
7522d5c66SAsim Jamshed /* for logging */
8522d5c66SAsim Jamshed #include "debug.h"
9522d5c66SAsim Jamshed /* for num_devices_* */
10522d5c66SAsim Jamshed #include "config.h"
11522d5c66SAsim Jamshed /* for netmap definitions */
12522d5c66SAsim Jamshed #define NETMAP_WITH_LIBS
13522d5c66SAsim Jamshed #include "netmap_user.h"
14522d5c66SAsim Jamshed /* for poll */
15522d5c66SAsim Jamshed #include <sys/poll.h>
16522d5c66SAsim Jamshed /* for NBBY */
17522d5c66SAsim Jamshed #include <sys/param.h>
18522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
19522d5c66SAsim Jamshed #define MAX_PKT_BURST			64
20522d5c66SAsim Jamshed #define ETHERNET_FRAME_SIZE		1514
21522d5c66SAsim Jamshed #define MAX_IFNAMELEN			(IF_NAMESIZE + 10)
22522d5c66SAsim Jamshed #define EXTRA_BUFS			512
23522d5c66SAsim Jamshed #define IDLE_POLL_WAIT			1 /* msecs */
24522d5c66SAsim Jamshed #define IDLE_POLL_COUNT			10
25522d5c66SAsim Jamshed //#define CONST_POLLING			1
26522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
27522d5c66SAsim Jamshed 
28522d5c66SAsim Jamshed struct netmap_private_context {
29522d5c66SAsim Jamshed 	struct nm_desc *local_nmd[MAX_DEVICES];
30522d5c66SAsim Jamshed 	unsigned char snd_pktbuf[MAX_DEVICES][ETHERNET_FRAME_SIZE];
31522d5c66SAsim Jamshed 	unsigned char *rcv_pktbuf[MAX_PKT_BURST];
32522d5c66SAsim Jamshed 	uint16_t rcv_pkt_len[MAX_PKT_BURST];
33522d5c66SAsim Jamshed 	uint16_t snd_pkt_size[MAX_DEVICES];
34522d5c66SAsim Jamshed 	uint8_t dev_poll_flag[MAX_DEVICES];
35522d5c66SAsim Jamshed 	uint8_t idle_poll_count;
36522d5c66SAsim Jamshed } __attribute__((aligned(__WORDSIZE)));
37522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
38522d5c66SAsim Jamshed void
netmap_init_handle(struct mtcp_thread_context * ctxt)39522d5c66SAsim Jamshed netmap_init_handle(struct mtcp_thread_context *ctxt)
40522d5c66SAsim Jamshed {
41522d5c66SAsim Jamshed 	struct netmap_private_context *npc;
42522d5c66SAsim Jamshed 	char ifname[MAX_IFNAMELEN];
43522d5c66SAsim Jamshed 	char nifname[MAX_IFNAMELEN];
44522d5c66SAsim Jamshed 	struct netdev_entry **ent;
45522d5c66SAsim Jamshed 	int j;
46522d5c66SAsim Jamshed 
47522d5c66SAsim Jamshed 	ent = g_config.mos->netdev_table->ent;
48522d5c66SAsim Jamshed 	/* create and initialize private I/O module context */
49522d5c66SAsim Jamshed 	ctxt->io_private_context = calloc(1, sizeof(struct netmap_private_context));
50522d5c66SAsim Jamshed 	if (ctxt->io_private_context == NULL) {
51522d5c66SAsim Jamshed 		TRACE_ERROR("Failed to initialize ctxt->io_private_context: "
52522d5c66SAsim Jamshed 			    "Can't allocate memory\n");
53522d5c66SAsim Jamshed 		exit(EXIT_FAILURE);
54522d5c66SAsim Jamshed 	}
55522d5c66SAsim Jamshed 
56522d5c66SAsim Jamshed 	npc = (struct netmap_private_context *)ctxt->io_private_context;
57522d5c66SAsim Jamshed 
58522d5c66SAsim Jamshed 	/* initialize per-thread netmap interfaces  */
59522d5c66SAsim Jamshed 	for (j = 0; j < g_config.mos->netdev_table->num; j++) {
60522d5c66SAsim Jamshed #if 0
61522d5c66SAsim Jamshed 		if (if_indextoname(devices_attached[j], ifname) == NULL) {
62522d5c66SAsim Jamshed 			TRACE_ERROR("Failed to initialize interface %s with ifidx: %d - "
63522d5c66SAsim Jamshed 				    "error string: %s\n",
64522d5c66SAsim Jamshed 				    ifname, devices_attached[j], strerror(errno));
65522d5c66SAsim Jamshed 			exit(EXIT_FAILURE);
66522d5c66SAsim Jamshed 		}
67522d5c66SAsim Jamshed #else
68522d5c66SAsim Jamshed 		strcpy(ifname, ent[j]->dev_name);
69522d5c66SAsim Jamshed #endif
70522d5c66SAsim Jamshed 		if (unlikely(g_config.mos->num_cores == 1))
71522d5c66SAsim Jamshed 			sprintf(nifname, "netmap:%s", ifname);
72522d5c66SAsim Jamshed 		else
73522d5c66SAsim Jamshed 			sprintf(nifname, "netmap:%s-%d", ifname, ctxt->cpu);
74522d5c66SAsim Jamshed 
75522d5c66SAsim Jamshed 		TRACE_INFO("Opening %s with j: %d (cpu: %d)\n", nifname, j, ctxt->cpu);
76522d5c66SAsim Jamshed 
77522d5c66SAsim Jamshed 		struct nmreq base_nmd;
78522d5c66SAsim Jamshed 		memset(&base_nmd, 0, sizeof(base_nmd));
79522d5c66SAsim Jamshed 		base_nmd.nr_arg3 = EXTRA_BUFS;
80522d5c66SAsim Jamshed 
81522d5c66SAsim Jamshed 		npc->local_nmd[j] = nm_open(nifname, &base_nmd, 0, NULL);
82522d5c66SAsim Jamshed 		if (npc->local_nmd[j] == NULL) {
83522d5c66SAsim Jamshed 			TRACE_ERROR("Unable to open %s: %s\n",
84522d5c66SAsim Jamshed 				    nifname, strerror(errno));
85522d5c66SAsim Jamshed 			exit(EXIT_FAILURE);
86522d5c66SAsim Jamshed 		}
87522d5c66SAsim Jamshed 	}
88522d5c66SAsim Jamshed }
89522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
90522d5c66SAsim Jamshed int
netmap_link_devices(struct mtcp_thread_context * ctxt)91522d5c66SAsim Jamshed netmap_link_devices(struct mtcp_thread_context *ctxt)
92522d5c66SAsim Jamshed {
93522d5c66SAsim Jamshed 	/* linking takes place during mtcp_init() */
94522d5c66SAsim Jamshed 
95522d5c66SAsim Jamshed 	return 0;
96522d5c66SAsim Jamshed }
97522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
98522d5c66SAsim Jamshed void
netmap_release_pkt(struct mtcp_thread_context * ctxt,int ifidx,unsigned char * pkt_data,int len)99522d5c66SAsim Jamshed netmap_release_pkt(struct mtcp_thread_context *ctxt, int ifidx, unsigned char *pkt_data, int len)
100522d5c66SAsim Jamshed {
101522d5c66SAsim Jamshed 	/*
102522d5c66SAsim Jamshed 	 * do nothing over here - memory reclamation
103522d5c66SAsim Jamshed 	 * will take place in dpdk_recv_pkts
104522d5c66SAsim Jamshed 	 */
105522d5c66SAsim Jamshed }
106522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
107522d5c66SAsim Jamshed int
netmap_send_pkts(struct mtcp_thread_context * ctxt,int nif)108522d5c66SAsim Jamshed netmap_send_pkts(struct mtcp_thread_context *ctxt, int nif)
109522d5c66SAsim Jamshed {
110522d5c66SAsim Jamshed 	int pkt_size, idx;
111522d5c66SAsim Jamshed 	struct netmap_private_context *npc;
112522d5c66SAsim Jamshed 	mtcp_manager_t mtcp;
113522d5c66SAsim Jamshed 
114522d5c66SAsim Jamshed 	npc = (struct netmap_private_context *)ctxt->io_private_context;
115522d5c66SAsim Jamshed 	idx = nif;
116522d5c66SAsim Jamshed 	pkt_size = npc->snd_pkt_size[idx];
117522d5c66SAsim Jamshed 	mtcp = ctxt->mtcp_manager;
118522d5c66SAsim Jamshed 
119522d5c66SAsim Jamshed 	/* assert-type statement */
120522d5c66SAsim Jamshed 	if (pkt_size == 0) return 0;
121522d5c66SAsim Jamshed 
122522d5c66SAsim Jamshed #ifdef NETSTAT
123522d5c66SAsim Jamshed 	mtcp->nstat.tx_packets[nif]++;
124*a834ea89SAsim Jamshed 	mtcp->nstat.tx_bytes[nif] += pkt_size + ETHER_OVR;
125522d5c66SAsim Jamshed #endif
126522d5c66SAsim Jamshed 
127522d5c66SAsim Jamshed  tx_again:
128522d5c66SAsim Jamshed 	if (nm_inject(npc->local_nmd[idx], npc->snd_pktbuf[idx], pkt_size) == 0) {
129522d5c66SAsim Jamshed 		TRACE_DBG("Failed to send pkt of size %d on interface: %d\n",
130522d5c66SAsim Jamshed 			  pkt_size, idx);
131522d5c66SAsim Jamshed 
132522d5c66SAsim Jamshed 		ioctl(npc->local_nmd[idx]->fd, NIOCTXSYNC, NULL);
133522d5c66SAsim Jamshed 		goto tx_again;
134522d5c66SAsim Jamshed 	}
135522d5c66SAsim Jamshed 
136522d5c66SAsim Jamshed #ifdef NETSTAT
137522d5c66SAsim Jamshed 	//	mtcp->nstat.rx_errors[idx]++;
138522d5c66SAsim Jamshed #endif
139522d5c66SAsim Jamshed 	npc->snd_pkt_size[idx] = 0;
140522d5c66SAsim Jamshed 
141522d5c66SAsim Jamshed 	return 1;
142522d5c66SAsim Jamshed }
143522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
144522d5c66SAsim Jamshed uint8_t *
netmap_get_wptr(struct mtcp_thread_context * ctxt,int nif,uint16_t pktsize)145522d5c66SAsim Jamshed netmap_get_wptr(struct mtcp_thread_context *ctxt, int nif, uint16_t pktsize)
146522d5c66SAsim Jamshed {
147522d5c66SAsim Jamshed 	struct netmap_private_context *npc;
148522d5c66SAsim Jamshed 	int idx = nif;
149522d5c66SAsim Jamshed 
150522d5c66SAsim Jamshed 	npc = (struct netmap_private_context *)ctxt->io_private_context;
151522d5c66SAsim Jamshed 	if (npc->snd_pkt_size[idx] != 0)
152522d5c66SAsim Jamshed 		netmap_send_pkts(ctxt, nif);
153522d5c66SAsim Jamshed 
154522d5c66SAsim Jamshed 	npc->snd_pkt_size[idx] = pktsize;
155522d5c66SAsim Jamshed 
156522d5c66SAsim Jamshed 	return (uint8_t *)npc->snd_pktbuf[idx];
157522d5c66SAsim Jamshed }
158522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
159522d5c66SAsim Jamshed int32_t
netmap_recv_pkts(struct mtcp_thread_context * ctxt,int ifidx)160522d5c66SAsim Jamshed netmap_recv_pkts(struct mtcp_thread_context *ctxt, int ifidx)
161522d5c66SAsim Jamshed {
162522d5c66SAsim Jamshed 	struct netmap_private_context *npc;
163522d5c66SAsim Jamshed 	struct nm_desc *d;
164522d5c66SAsim Jamshed 	npc = (struct netmap_private_context *)ctxt->io_private_context;
165522d5c66SAsim Jamshed 	d = npc->local_nmd[ifidx];
166522d5c66SAsim Jamshed 
167522d5c66SAsim Jamshed 	int p = 0;
168522d5c66SAsim Jamshed 	int c, got = 0, ri = d->cur_rx_ring;
169522d5c66SAsim Jamshed 	int n = d->last_rx_ring - d->first_rx_ring + 1;
170522d5c66SAsim Jamshed 	int cnt = MAX_PKT_BURST;
171522d5c66SAsim Jamshed 
172522d5c66SAsim Jamshed 
173522d5c66SAsim Jamshed 
174522d5c66SAsim Jamshed 	for (c = 0; c < n && cnt != got && npc->dev_poll_flag[ifidx]; c++) {
175522d5c66SAsim Jamshed 		/* compute current ring to use */
176522d5c66SAsim Jamshed 		struct netmap_ring *ring;
177522d5c66SAsim Jamshed 
178522d5c66SAsim Jamshed 		ri = d->cur_rx_ring + c;
179522d5c66SAsim Jamshed 		if (ri > d->last_rx_ring)
180522d5c66SAsim Jamshed 			ri = d->first_rx_ring;
181522d5c66SAsim Jamshed 		ring = NETMAP_RXRING(d->nifp, ri);
182522d5c66SAsim Jamshed 		for ( ; !nm_ring_empty(ring) && cnt != got; got++) {
183522d5c66SAsim Jamshed 			u_int i = ring->cur;
184522d5c66SAsim Jamshed 			u_int idx = ring->slot[i].buf_idx;
185522d5c66SAsim Jamshed 			npc->rcv_pktbuf[p] = (u_char *)NETMAP_BUF(ring, idx);
186522d5c66SAsim Jamshed 			npc->rcv_pkt_len[p] = ring->slot[i].len;
187522d5c66SAsim Jamshed 			p++;
188522d5c66SAsim Jamshed 			ring->head = ring->cur = nm_ring_next(ring, i);
189522d5c66SAsim Jamshed 		}
190522d5c66SAsim Jamshed 	}
191522d5c66SAsim Jamshed 	d->cur_rx_ring = ri;
192522d5c66SAsim Jamshed 
193522d5c66SAsim Jamshed 	npc->dev_poll_flag[ifidx] = 0;
194522d5c66SAsim Jamshed 
195522d5c66SAsim Jamshed 	return p;
196522d5c66SAsim Jamshed }
197522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
198522d5c66SAsim Jamshed uint8_t *
netmap_get_rptr(struct mtcp_thread_context * ctxt,int ifidx,int index,uint16_t * len)199522d5c66SAsim Jamshed netmap_get_rptr(struct mtcp_thread_context *ctxt, int ifidx, int index, uint16_t *len)
200522d5c66SAsim Jamshed {
201522d5c66SAsim Jamshed 	struct netmap_private_context *npc;
202522d5c66SAsim Jamshed 	npc = (struct netmap_private_context *)ctxt->io_private_context;
203522d5c66SAsim Jamshed 
204522d5c66SAsim Jamshed 	*len = npc->rcv_pkt_len[index];
205522d5c66SAsim Jamshed 	return (unsigned char *)npc->rcv_pktbuf[index];
206522d5c66SAsim Jamshed }
207522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
208522d5c66SAsim Jamshed int32_t
netmap_select(struct mtcp_thread_context * ctxt)209522d5c66SAsim Jamshed netmap_select(struct mtcp_thread_context *ctxt)
210522d5c66SAsim Jamshed {
211522d5c66SAsim Jamshed 	int i, rc;
212522d5c66SAsim Jamshed 	struct pollfd pfd[MAX_DEVICES];
213522d5c66SAsim Jamshed 	struct netmap_private_context *npc =
214522d5c66SAsim Jamshed 		(struct netmap_private_context *)ctxt->io_private_context;
215522d5c66SAsim Jamshed 
216522d5c66SAsim Jamshed 	/* see if num_devices have been registered */
217522d5c66SAsim Jamshed 	if (npc->local_nmd[0] == NULL)
218522d5c66SAsim Jamshed 		return -1;
219522d5c66SAsim Jamshed 
220522d5c66SAsim Jamshed 	for (i = 0; i < g_config.mos->netdev_table->num; i++) {
221522d5c66SAsim Jamshed 		pfd[i].fd = npc->local_nmd[i]->fd;
222522d5c66SAsim Jamshed 		pfd[i].events = POLLIN;
223522d5c66SAsim Jamshed 	}
224522d5c66SAsim Jamshed 
225522d5c66SAsim Jamshed #ifndef CONST_POLLING
226522d5c66SAsim Jamshed 	if (npc->idle_poll_count >= IDLE_POLL_COUNT) {
227522d5c66SAsim Jamshed 		rc = poll(pfd, g_config.mos->netdev_table->num, IDLE_POLL_WAIT);
228522d5c66SAsim Jamshed 	} else
229522d5c66SAsim Jamshed #endif
230522d5c66SAsim Jamshed 		{
231522d5c66SAsim Jamshed 			rc = poll(pfd, g_config.mos->netdev_table->num, 0);
232522d5c66SAsim Jamshed 		}
233522d5c66SAsim Jamshed 
234522d5c66SAsim Jamshed 	npc->idle_poll_count = (rc == 0) ? (npc->idle_poll_count + 1) : 0;
235522d5c66SAsim Jamshed 
236522d5c66SAsim Jamshed 	for (i = 0; rc > 0 && i < g_config.mos->netdev_table->num; i++)
237522d5c66SAsim Jamshed 		if (!(pfd[i].revents & (POLLERR)))
238522d5c66SAsim Jamshed 			npc->dev_poll_flag[i] = 1;
239522d5c66SAsim Jamshed 	return 0;
240522d5c66SAsim Jamshed }
241522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
242522d5c66SAsim Jamshed int
netmap_get_nif(struct ifreq * ifr)243522d5c66SAsim Jamshed netmap_get_nif(struct ifreq *ifr)
244522d5c66SAsim Jamshed {
245522d5c66SAsim Jamshed 	int i;
246522d5c66SAsim Jamshed 	struct netdev_entry **ent = g_config.mos->netdev_table->ent;
247522d5c66SAsim Jamshed 
248522d5c66SAsim Jamshed 	for (i = 0; i < g_config.mos->netdev_table->num; i++)
249522d5c66SAsim Jamshed 		if (!strcmp(ifr->ifr_name, ent[i]->dev_name))
250522d5c66SAsim Jamshed 			return i;
251522d5c66SAsim Jamshed 
252522d5c66SAsim Jamshed 	return -1;
253522d5c66SAsim Jamshed }
254522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
255522d5c66SAsim Jamshed int32_t
netmap_dev_ioctl(struct mtcp_thread_context * ctx,int nif,int cmd,void * argp)256522d5c66SAsim Jamshed netmap_dev_ioctl(struct mtcp_thread_context *ctx, int nif, int cmd, void *argp)
257522d5c66SAsim Jamshed {
258522d5c66SAsim Jamshed 	/* unimplemented */
259522d5c66SAsim Jamshed 	return -1;
260522d5c66SAsim Jamshed }
261522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
262522d5c66SAsim Jamshed void
netmap_destroy_handle(struct mtcp_thread_context * ctxt)263522d5c66SAsim Jamshed netmap_destroy_handle(struct mtcp_thread_context *ctxt)
264522d5c66SAsim Jamshed {
265522d5c66SAsim Jamshed 	int i;
266522d5c66SAsim Jamshed 	struct netmap_private_context *npc;
267522d5c66SAsim Jamshed 
268522d5c66SAsim Jamshed 	npc = (struct netmap_private_context *)ctxt->io_private_context;
269522d5c66SAsim Jamshed 
270522d5c66SAsim Jamshed 	for (i = 0; i < g_config.mos->netdev_table->num; i++)
271522d5c66SAsim Jamshed 		close(npc->local_nmd[i]->fd);
272522d5c66SAsim Jamshed }
273522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
274522d5c66SAsim Jamshed void
netmap_load_module_upper_half(void)275522d5c66SAsim Jamshed netmap_load_module_upper_half(void)
276522d5c66SAsim Jamshed {
277522d5c66SAsim Jamshed 	int i;
278522d5c66SAsim Jamshed 	int num_dev;
279522d5c66SAsim Jamshed 	uint64_t cpu_mask;
280522d5c66SAsim Jamshed 	int queue_range;
281522d5c66SAsim Jamshed 
282522d5c66SAsim Jamshed 	num_dev = g_config.mos->netdev_table->num;
283522d5c66SAsim Jamshed 
284522d5c66SAsim Jamshed 	for (i = 0; i < num_dev; i++) {
285522d5c66SAsim Jamshed 		cpu_mask = g_config.mos->netdev_table->ent[i]->cpu_mask;
286522d5c66SAsim Jamshed 		queue_range = sizeof(cpu_mask) * NBBY - __builtin_clzll(cpu_mask);
287522d5c66SAsim Jamshed 		num_queues =  (num_queues < queue_range) ?
288522d5c66SAsim Jamshed 			queue_range : num_queues;
289522d5c66SAsim Jamshed 	}
290522d5c66SAsim Jamshed }
291522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
2927e4ac3deSAsim Jamshed static void
set_promisc(char * ifname)2937e4ac3deSAsim Jamshed set_promisc(char *ifname)
2947e4ac3deSAsim Jamshed {
2957e4ac3deSAsim Jamshed 	int fd, ret;
2967e4ac3deSAsim Jamshed 	struct ifreq eth;
2977e4ac3deSAsim Jamshed 
2987e4ac3deSAsim Jamshed 	fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
2997e4ac3deSAsim Jamshed 	if (fd == -1) {
3007e4ac3deSAsim Jamshed 		TRACE_ERROR("Couldn't open socket!\n");
3017e4ac3deSAsim Jamshed 		return;
3027e4ac3deSAsim Jamshed 	}
3037e4ac3deSAsim Jamshed 	strcpy(eth.ifr_name, ifname);
3047e4ac3deSAsim Jamshed 	ret = ioctl(fd, SIOCGIFFLAGS, &eth);
3057e4ac3deSAsim Jamshed 	if (ret == -1) {
3067e4ac3deSAsim Jamshed 		TRACE_ERROR("Get ioctl for %s failed!\n",
3077e4ac3deSAsim Jamshed 			    ifname);
3087e4ac3deSAsim Jamshed 		close(fd);
3097e4ac3deSAsim Jamshed 		return;
3107e4ac3deSAsim Jamshed 	}
3117e4ac3deSAsim Jamshed 
3127e4ac3deSAsim Jamshed 	if (eth.ifr_flags & IFF_PROMISC) {
3137e4ac3deSAsim Jamshed 		TRACE_ERROR("Interface %s is already set to "
3147e4ac3deSAsim Jamshed 			    "promiscuous mode\n", ifname);
3157e4ac3deSAsim Jamshed 		close(fd);
3167e4ac3deSAsim Jamshed 		return;
3177e4ac3deSAsim Jamshed 	}
3187e4ac3deSAsim Jamshed 	eth.ifr_flags |= IFF_PROMISC;
3197e4ac3deSAsim Jamshed 
3207e4ac3deSAsim Jamshed 	ret = ioctl(fd, SIOCSIFFLAGS, &eth);
3217e4ac3deSAsim Jamshed 	if (ret == -1) {
3227e4ac3deSAsim Jamshed 		TRACE_ERROR("Set ioctl failed for %s\n", ifname);
3237e4ac3deSAsim Jamshed 		close(fd);
3247e4ac3deSAsim Jamshed 		return;
3257e4ac3deSAsim Jamshed 	}
3267e4ac3deSAsim Jamshed 
3277e4ac3deSAsim Jamshed 	close(fd);
3287e4ac3deSAsim Jamshed 
3297e4ac3deSAsim Jamshed }
3307e4ac3deSAsim Jamshed /*----------------------------------------------------------------------------*/
3317e4ac3deSAsim Jamshed void
netmap_load_module_lower_half(void)3327e4ac3deSAsim Jamshed netmap_load_module_lower_half(void)
3337e4ac3deSAsim Jamshed {
3347e4ac3deSAsim Jamshed 	struct netdev_entry **ent;
3357e4ac3deSAsim Jamshed 	int j;
3367e4ac3deSAsim Jamshed 
3377e4ac3deSAsim Jamshed 	ent = g_config.mos->netdev_table->ent;
3387e4ac3deSAsim Jamshed 
3397e4ac3deSAsim Jamshed 	for (j = 0; j < g_config.mos->netdev_table->num; j++) {
3407e4ac3deSAsim Jamshed 		set_promisc(ent[j]->dev_name);
3417e4ac3deSAsim Jamshed 	}
3427e4ac3deSAsim Jamshed }
3437e4ac3deSAsim Jamshed /*----------------------------------------------------------------------------*/
344522d5c66SAsim Jamshed io_module_func netmap_module_func = {
345522d5c66SAsim Jamshed 	.load_module_upper_half	   = netmap_load_module_upper_half,
3467e4ac3deSAsim Jamshed 	.load_module_lower_half	   = netmap_load_module_lower_half,
347522d5c66SAsim Jamshed 	.init_handle		   = netmap_init_handle,
348522d5c66SAsim Jamshed 	.link_devices		   = netmap_link_devices,
349522d5c66SAsim Jamshed 	.release_pkt		   = netmap_release_pkt,
350522d5c66SAsim Jamshed 	.send_pkts		   = netmap_send_pkts,
351522d5c66SAsim Jamshed 	.get_wptr   		   = netmap_get_wptr,
352522d5c66SAsim Jamshed 	.set_wptr		   = NULL,
353522d5c66SAsim Jamshed 	.recv_pkts		   = netmap_recv_pkts,
354522d5c66SAsim Jamshed 	.get_rptr	   	   = netmap_get_rptr,
355522d5c66SAsim Jamshed 	.get_nif		   = netmap_get_nif,
356522d5c66SAsim Jamshed 	.select			   = netmap_select,
357522d5c66SAsim Jamshed 	.destroy_handle		   = netmap_destroy_handle,
358522d5c66SAsim Jamshed 	.dev_ioctl		   = netmap_dev_ioctl,
359522d5c66SAsim Jamshed };
360522d5c66SAsim Jamshed /*----------------------------------------------------------------------------*/
361522d5c66SAsim Jamshed 
362