New upstream version 18.08
[deb_dpdk.git] / examples / netmap_compat / lib / compat_netmap.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <errno.h>
6 #include <inttypes.h>
7 #include <poll.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <net/if.h>
11 #include <sys/types.h>
12 #include <sys/resource.h>
13 #include <sys/mman.h>
14
15 #include <rte_common.h>
16 #include <rte_errno.h>
17 #include <rte_ethdev.h>
18 #include <rte_log.h>
19 #include <rte_malloc.h>
20 #include <rte_mbuf.h>
21 #include <rte_spinlock.h>
22 #include <rte_string_fns.h>
23
24 #include "compat_netmap.h"
25
26 struct netmap_port {
27         struct rte_mempool   *pool;
28         struct netmap_if     *nmif;
29         struct rte_eth_conf   eth_conf;
30         struct rte_eth_txconf tx_conf;
31         struct rte_eth_rxconf rx_conf;
32         int32_t  socket_id;
33         uint16_t nr_tx_rings;
34         uint16_t nr_rx_rings;
35         uint32_t nr_tx_slots;
36         uint32_t nr_rx_slots;
37         uint16_t tx_burst;
38         uint16_t rx_burst;
39         uint32_t fd;
40 };
41
42 struct fd_port {
43         uint32_t port;
44 };
45
46 #ifndef POLLRDNORM
47 #define POLLRDNORM      0x0040
48 #endif
49
50 #ifndef POLLWRNORM
51 #define POLLWRNORM      0x0100
52 #endif
53
54 #define FD_PORT_FREE    UINT32_MAX
55 #define FD_PORT_RSRV    (FD_PORT_FREE - 1)
56
57 struct netmap_state {
58         struct rte_netmap_conf conf;
59         uintptr_t buf_start;
60         void     *mem;
61         uint32_t  mem_sz;
62         uint32_t  netif_memsz;
63 };
64
65
66 #define COMPAT_NETMAP_MAX_NOFILE        (2 * RTE_MAX_ETHPORTS)
67 #define COMPAT_NETMAP_MAX_BURST         64
68 #define COMPAT_NETMAP_MAX_PKT_PER_SYNC  (2 * COMPAT_NETMAP_MAX_BURST)
69
70 static struct netmap_port ports[RTE_MAX_ETHPORTS];
71 static struct netmap_state netmap;
72
73 static struct fd_port fd_port[COMPAT_NETMAP_MAX_NOFILE];
74 static const int next_fd_start = RLIMIT_NOFILE + 1;
75 static rte_spinlock_t netmap_lock;
76
77 #define IDX_TO_FD(x)    ((x) + next_fd_start)
78 #define FD_TO_IDX(x)    ((x) - next_fd_start)
79 #define FD_VALID(x)     ((x) >= next_fd_start && \
80         (x) < (typeof (x))(RTE_DIM(fd_port) + next_fd_start))
81
82 #define PORT_NUM_RINGS  (2 * netmap.conf.max_rings)
83 #define PORT_NUM_SLOTS  (PORT_NUM_RINGS * netmap.conf.max_slots)
84
85 #define BUF_IDX(port, ring, slot)            \
86         (((port) * PORT_NUM_RINGS + (ring)) * netmap.conf.max_slots + \
87         (slot))
88
89 #define NETMAP_IF_RING_OFS(rid, rings, slots)   ({\
90         struct netmap_if *_if;                    \
91         struct netmap_ring *_rg;                  \
92         sizeof(*_if) +                            \
93         (rings) * sizeof(_if->ring_ofs[0]) +      \
94         (rid) * sizeof(*_rg) +                    \
95         (slots) * sizeof(_rg->slot[0]);           \
96         })
97
98 static void netmap_unregif(uint32_t idx, uint32_t port);
99
100
101 static int32_t
102 ifname_to_portid(const char *ifname, uint16_t *port)
103 {
104         char *endptr;
105         uint64_t portid;
106
107         errno = 0;
108         portid = strtoul(ifname, &endptr, 10);
109         if (endptr == ifname || *endptr != '\0' ||
110                         portid >= RTE_DIM(ports) || errno != 0)
111                 return -EINVAL;
112
113         *port = portid;
114         return 0;
115 }
116
117 /**
118  * Given a dpdk mbuf, fill in the Netmap slot in ring r and its associated
119  * buffer with the data held by the mbuf.
120  * Note that mbuf chains are not supported.
121  */
122 static void
123 mbuf_to_slot(struct rte_mbuf *mbuf, struct netmap_ring *r, uint32_t index)
124 {
125         char *data;
126         uint16_t length;
127
128         data   = rte_pktmbuf_mtod(mbuf, char *);
129         length = rte_pktmbuf_data_len(mbuf);
130
131         if (length > r->nr_buf_size)
132                 length = 0;
133
134         r->slot[index].len = length;
135         rte_memcpy(NETMAP_BUF(r, r->slot[index].buf_idx), data, length);
136 }
137
138 /**
139  * Given a Netmap ring and a slot index for that ring, construct a dpdk mbuf
140  * from the data held in the buffer associated with the slot.
141  * Allocation/deallocation of the dpdk mbuf are the responsibility of the
142  * caller.
143  * Note that mbuf chains are not supported.
144  */
145 static void
146 slot_to_mbuf(struct netmap_ring *r, uint32_t index, struct rte_mbuf *mbuf)
147 {
148         char *data;
149         uint16_t length;
150
151         rte_pktmbuf_reset(mbuf);
152         length = r->slot[index].len;
153         data = rte_pktmbuf_append(mbuf, length);
154
155         if (data != NULL)
156             rte_memcpy(data, NETMAP_BUF(r, r->slot[index].buf_idx), length);
157 }
158
159 static int32_t
160 fd_reserve(void)
161 {
162         uint32_t i;
163
164         for (i = 0; i != RTE_DIM(fd_port) && fd_port[i].port != FD_PORT_FREE;
165                         i++)
166                 ;
167
168         if (i == RTE_DIM(fd_port))
169                 return -ENOMEM;
170
171         fd_port[i].port = FD_PORT_RSRV;
172         return IDX_TO_FD(i);
173 }
174
175 static int32_t
176 fd_release(int32_t fd)
177 {
178         uint32_t idx, port;
179
180         idx = FD_TO_IDX(fd);
181
182         if (!FD_VALID(fd) || (port = fd_port[idx].port) == FD_PORT_FREE)
183                 return -EINVAL;
184
185         /* if we still have a valid port attached, release the port */
186         if (port < RTE_DIM(ports) && ports[port].fd == idx) {
187                 netmap_unregif(idx, port);
188         }
189
190         fd_port[idx].port = FD_PORT_FREE;
191         return 0;
192 }
193
194 static int
195 check_nmreq(struct nmreq *req, uint16_t *port)
196 {
197         int32_t rc;
198         uint16_t portid;
199
200         if (req == NULL)
201                 return -EINVAL;
202
203         if (req->nr_version != NETMAP_API) {
204                 req->nr_version = NETMAP_API;
205                 return -EINVAL;
206         }
207
208         if ((rc = ifname_to_portid(req->nr_name, &portid)) != 0) {
209                 RTE_LOG(ERR, USER1, "Invalid interface name:\"%s\" "
210                         "in NIOCGINFO call\n", req->nr_name);
211                 return rc;
212         }
213
214         if (ports[portid].pool == NULL) {
215                 RTE_LOG(ERR, USER1, "Misconfigured portid %u\n", portid);
216                 return -EINVAL;
217         }
218
219         *port = portid;
220         return 0;
221 }
222
223 /**
224  * Simulate a Netmap NIOCGINFO ioctl: given a struct nmreq holding an interface
225  * name (a port number in our case), fill the struct nmreq in with advisory
226  * information about the interface: number of rings and their size, total memory
227  * required in the map, ...
228  * Those are preconfigured using rte_eth_{,tx,rx}conf and
229  * rte_netmap_port_conf structures
230  * and calls to rte_netmap_init_port() in the Netmap application.
231  */
232 static int
233 ioctl_niocginfo(__rte_unused int fd, void * param)
234 {
235         uint16_t portid;
236         struct nmreq *req;
237         int32_t rc;
238
239         req = (struct nmreq *)param;
240         if ((rc = check_nmreq(req, &portid)) != 0)
241                 return rc;
242
243         req->nr_tx_rings = (uint16_t)(ports[portid].nr_tx_rings - 1);
244         req->nr_rx_rings = (uint16_t)(ports[portid].nr_rx_rings - 1);
245         req->nr_tx_slots = ports[portid].nr_tx_slots;
246         req->nr_rx_slots = ports[portid].nr_rx_slots;
247
248         /* in current implementation we have all NETIFs shared aone region. */
249         req->nr_memsize = netmap.mem_sz;
250         req->nr_offset = 0;
251
252         return 0;
253 }
254
255 static void
256 netmap_ring_setup(struct netmap_ring *ring, uint16_t port, uint32_t ringid,
257         uint32_t num_slots)
258 {
259         uint32_t j;
260
261         ring->buf_ofs = netmap.buf_start - (uintptr_t)ring;
262         ring->num_slots = num_slots;
263         ring->cur = 0;
264         ring->reserved = 0;
265         ring->nr_buf_size = netmap.conf.max_bufsz;
266         ring->flags = 0;
267         ring->ts.tv_sec = 0;
268         ring->ts.tv_usec = 0;
269
270         for (j = 0; j < ring->num_slots; j++) {
271                 ring->slot[j].buf_idx = BUF_IDX(port, ringid, j);
272                 ring->slot[j].len = 0;
273                 ring->flags = 0;
274         }
275 }
276
277 static int
278 netmap_regif(struct nmreq *req, uint32_t idx, uint16_t port)
279 {
280         struct netmap_if *nmif;
281         struct netmap_ring *ring;
282         uint32_t i, slots, start_ring;
283         int32_t rc;
284
285         if (ports[port].fd < RTE_DIM(fd_port)) {
286                 RTE_LOG(ERR, USER1, "port %u already in use by fd: %u\n",
287                         port, IDX_TO_FD(ports[port].fd));
288                 return -EBUSY;
289         }
290         if (fd_port[idx].port != FD_PORT_RSRV) {
291                 RTE_LOG(ERR, USER1, "fd: %u is misconfigured\n",
292                         IDX_TO_FD(idx));
293                 return -EBUSY;
294         }
295
296         nmif = ports[port].nmif;
297
298         /* setup netmap_if fields. */
299         memset(nmif, 0, netmap.netif_memsz);
300
301         /* only ALL rings supported right now. */
302         if (req->nr_ringid != 0)
303                 return -EINVAL;
304
305         snprintf(nmif->ni_name, sizeof(nmif->ni_name), "%s", req->nr_name);
306         nmif->ni_version  = req->nr_version;
307
308         /* Netmap uses ni_(r|t)x_rings + 1 */
309         nmif->ni_rx_rings = ports[port].nr_rx_rings - 1;
310         nmif->ni_tx_rings = ports[port].nr_tx_rings - 1;
311
312         /*
313          * Setup TX rings and slots.
314          * Refer to the comments in netmap.h for details
315          */
316
317         slots = 0;
318         for (i = 0; i < nmif->ni_tx_rings + 1; i++) {
319
320                 nmif->ring_ofs[i] = NETMAP_IF_RING_OFS(i,
321                         PORT_NUM_RINGS, slots);
322
323                 ring = NETMAP_TXRING(nmif, i);
324                 netmap_ring_setup(ring, port, i, ports[port].nr_tx_slots);
325                 ring->avail = ring->num_slots;
326
327                 slots += ports[port].nr_tx_slots;
328         }
329
330         /*
331          * Setup  RX rings and slots.
332          * Refer to the comments in netmap.h for details
333          */
334
335         start_ring = i;
336
337         for (; i < nmif->ni_rx_rings + 1 + start_ring; i++) {
338
339                 nmif->ring_ofs[i] = NETMAP_IF_RING_OFS(i,
340                         PORT_NUM_RINGS, slots);
341
342                 ring = NETMAP_RXRING(nmif, (i - start_ring));
343                 netmap_ring_setup(ring, port, i, ports[port].nr_rx_slots);
344                 ring->avail = 0;
345
346                 slots += ports[port].nr_rx_slots;
347         }
348
349         if ((rc = rte_eth_dev_start(port)) < 0) {
350                 RTE_LOG(ERR, USER1,
351                         "Couldn't start ethernet device %s (error %d)\n",
352                         req->nr_name, rc);
353             return rc;
354         }
355
356         /* setup fdi <--> port relationtip. */
357         ports[port].fd = idx;
358         fd_port[idx].port = port;
359
360         req->nr_memsize = netmap.mem_sz;
361         req->nr_offset = (uintptr_t)nmif - (uintptr_t)netmap.mem;
362
363         return 0;
364 }
365
366 /**
367  * Simulate a Netmap NIOCREGIF ioctl:
368  */
369 static int
370 ioctl_niocregif(int32_t fd, void * param)
371 {
372         uint16_t portid;
373         int32_t rc;
374         uint32_t idx;
375         struct nmreq *req;
376
377         req = (struct nmreq *)param;
378         if ((rc = check_nmreq(req, &portid)) != 0)
379                 return rc;
380
381         idx = FD_TO_IDX(fd);
382
383         rte_spinlock_lock(&netmap_lock);
384         rc = netmap_regif(req, idx, portid);
385         rte_spinlock_unlock(&netmap_lock);
386
387         return rc;
388 }
389
390 static void
391 netmap_unregif(uint32_t idx, uint32_t port)
392 {
393         fd_port[idx].port = FD_PORT_RSRV;
394         ports[port].fd = UINT32_MAX;
395         rte_eth_dev_stop(port);
396 }
397
398 /**
399  * Simulate a Netmap NIOCUNREGIF ioctl: put an interface running in Netmap
400  * mode back in "normal" mode. In our case, we just stop the port associated
401  * with this file descriptor.
402  */
403 static int
404 ioctl_niocunregif(int fd)
405 {
406         uint32_t idx, port;
407         int32_t rc;
408
409         idx = FD_TO_IDX(fd);
410
411         rte_spinlock_lock(&netmap_lock);
412
413         port = fd_port[idx].port;
414         if (port < RTE_DIM(ports) && ports[port].fd == idx) {
415                 netmap_unregif(idx, port);
416                 rc = 0;
417         } else {
418                 RTE_LOG(ERR, USER1,
419                         "%s: %d is not associated with valid port\n",
420                         __func__, fd);
421                 rc = -EINVAL;
422         }
423
424         rte_spinlock_unlock(&netmap_lock);
425         return rc;
426 }
427
428 /**
429  * A call to rx_sync_ring will try to fill a Netmap RX ring with as many
430  * packets as it can hold coming from its dpdk port.
431  */
432 static inline int
433 rx_sync_ring(struct netmap_ring *ring, uint16_t port, uint16_t ring_number,
434         uint16_t max_burst)
435 {
436         int32_t i, n_rx;
437         uint16_t burst_size;
438         uint32_t cur_slot, n_free_slots;
439         struct rte_mbuf *rx_mbufs[COMPAT_NETMAP_MAX_BURST];
440
441         n_free_slots = ring->num_slots - (ring->avail + ring->reserved);
442         n_free_slots = RTE_MIN(n_free_slots, max_burst);
443         cur_slot = (ring->cur + ring->avail) & (ring->num_slots - 1);
444
445         while (n_free_slots) {
446                 burst_size = (uint16_t)RTE_MIN(n_free_slots, RTE_DIM(rx_mbufs));
447
448                 /* receive up to burst_size packets from the NIC's queue */
449                 n_rx = rte_eth_rx_burst(port, ring_number, rx_mbufs,
450                         burst_size);
451
452                 if (n_rx == 0)
453                         return 0;
454                 if (unlikely(n_rx < 0))
455                         return -1;
456
457                 /* Put those n_rx packets in the Netmap structures */
458                 for (i = 0; i < n_rx ; i++) {
459                         mbuf_to_slot(rx_mbufs[i], ring, cur_slot);
460                         rte_pktmbuf_free(rx_mbufs[i]);
461                         cur_slot = NETMAP_RING_NEXT(ring, cur_slot);
462                 }
463
464                 /* Update the Netmap ring structure to reflect the change */
465                 ring->avail += n_rx;
466                 n_free_slots -= n_rx;
467         }
468
469         return 0;
470 }
471
472 static inline int
473 rx_sync_if(uint32_t port)
474 {
475         uint16_t burst;
476         uint32_t i, rc;
477         struct netmap_if *nifp;
478         struct netmap_ring *r;
479
480         nifp = ports[port].nmif;
481         burst = ports[port].rx_burst;
482         rc = 0;
483
484         for (i = 0; i < nifp->ni_rx_rings + 1; i++) {
485                 r = NETMAP_RXRING(nifp, i);
486                 rx_sync_ring(r, port, (uint16_t)i, burst);
487                 rc += r->avail;
488         }
489
490         return rc;
491 }
492
493 /**
494  * Simulate a Netmap NIOCRXSYNC ioctl:
495  */
496 static int
497 ioctl_niocrxsync(int fd)
498 {
499         uint32_t idx, port;
500
501         idx = FD_TO_IDX(fd);
502         if ((port = fd_port[idx].port) < RTE_DIM(ports) &&
503                         ports[port].fd == idx) {
504                 return rx_sync_if(fd_port[idx].port);
505         } else  {
506                 return -EINVAL;
507         }
508 }
509
510 /**
511  * A call to tx_sync_ring will try to empty a Netmap TX ring by converting its
512  * buffers into rte_mbufs and sending them out on the rings's dpdk port.
513  */
514 static int
515 tx_sync_ring(struct netmap_ring *ring, uint16_t port, uint16_t ring_number,
516         struct rte_mempool *pool, uint16_t max_burst)
517 {
518         uint32_t i, n_tx;
519         uint16_t burst_size;
520         uint32_t cur_slot, n_used_slots;
521         struct rte_mbuf *tx_mbufs[COMPAT_NETMAP_MAX_BURST];
522
523         n_used_slots = ring->num_slots - ring->avail;
524         n_used_slots = RTE_MIN(n_used_slots, max_burst);
525         cur_slot = (ring->cur + ring->avail) & (ring->num_slots - 1);
526
527         while (n_used_slots) {
528                 burst_size = (uint16_t)RTE_MIN(n_used_slots, RTE_DIM(tx_mbufs));
529
530                 for (i = 0; i < burst_size; i++) {
531                         tx_mbufs[i] = rte_pktmbuf_alloc(pool);
532                         if (tx_mbufs[i] == NULL)
533                                 goto err;
534
535                         slot_to_mbuf(ring, cur_slot, tx_mbufs[i]);
536                         cur_slot = NETMAP_RING_NEXT(ring, cur_slot);
537                 }
538
539                 n_tx = rte_eth_tx_burst(port, ring_number, tx_mbufs,
540                         burst_size);
541
542                 /* Update the Netmap ring structure to reflect the change */
543                 ring->avail += n_tx;
544                 n_used_slots -= n_tx;
545
546                 /* Return the mbufs that failed to transmit to their pool */
547                 if (unlikely(n_tx != burst_size)) {
548                         for (i = n_tx; i < burst_size; i++)
549                                 rte_pktmbuf_free(tx_mbufs[i]);
550                         break;
551                 }
552         }
553
554         return 0;
555
556 err:
557         for (; i == 0; --i)
558                 rte_pktmbuf_free(tx_mbufs[i]);
559
560         RTE_LOG(ERR, USER1,
561                 "Couldn't get mbuf from mempool is the mempool too small?\n");
562         return -1;
563 }
564
565 static int
566 tx_sync_if(uint32_t port)
567 {
568         uint16_t burst;
569         uint32_t i, rc;
570         struct netmap_if *nifp;
571         struct netmap_ring *r;
572         struct rte_mempool *mp;
573
574         nifp = ports[port].nmif;
575         mp = ports[port].pool;
576         burst = ports[port].tx_burst;
577         rc = 0;
578
579         for (i = 0; i < nifp->ni_tx_rings + 1; i++) {
580                 r = NETMAP_TXRING(nifp, i);
581                 tx_sync_ring(r, port, (uint16_t)i, mp, burst);
582                 rc += r->avail;
583         }
584
585         return rc;
586 }
587
588 /**
589  * Simulate a Netmap NIOCTXSYNC ioctl:
590  */
591 static inline int
592 ioctl_nioctxsync(int fd)
593 {
594         uint32_t idx, port;
595
596         idx = FD_TO_IDX(fd);
597         if ((port = fd_port[idx].port) < RTE_DIM(ports) &&
598                         ports[port].fd == idx) {
599                 return tx_sync_if(fd_port[idx].port);
600         } else  {
601                 return -EINVAL;
602         }
603 }
604
605 /**
606  * Give the library a mempool of rte_mbufs with which it can do the
607  * rte_mbuf <--> netmap slot conversions.
608  */
609 int
610 rte_netmap_init(const struct rte_netmap_conf *conf)
611 {
612         size_t buf_ofs, nmif_sz, sz;
613         size_t port_rings, port_slots, port_bufs;
614         uint32_t i, port_num;
615
616         port_num = RTE_MAX_ETHPORTS;
617         port_rings = 2 * conf->max_rings;
618         port_slots = port_rings * conf->max_slots;
619         port_bufs = port_slots;
620
621         nmif_sz = NETMAP_IF_RING_OFS(port_rings, port_rings, port_slots);
622         sz = nmif_sz * port_num;
623
624         buf_ofs = RTE_ALIGN_CEIL(sz, RTE_CACHE_LINE_SIZE);
625         sz = buf_ofs + port_bufs * conf->max_bufsz * port_num;
626
627         if (sz > UINT32_MAX ||
628                         (netmap.mem = rte_zmalloc_socket(__func__, sz,
629                         RTE_CACHE_LINE_SIZE, conf->socket_id)) == NULL) {
630                 RTE_LOG(ERR, USER1, "%s: failed to allocate %zu bytes\n",
631                         __func__, sz);
632                 return -ENOMEM;
633         }
634
635         netmap.mem_sz = sz;
636         netmap.netif_memsz = nmif_sz;
637         netmap.buf_start = (uintptr_t)netmap.mem + buf_ofs;
638         netmap.conf = *conf;
639
640         rte_spinlock_init(&netmap_lock);
641
642         /* Mark all ports as unused and set NETIF pointer. */
643         for (i = 0; i != RTE_DIM(ports); i++) {
644                 ports[i].fd = UINT32_MAX;
645                 ports[i].nmif = (struct netmap_if *)
646                         ((uintptr_t)netmap.mem + nmif_sz * i);
647         }
648
649         /* Mark all fd_ports as unused. */
650         for (i = 0; i != RTE_DIM(fd_port); i++) {
651                 fd_port[i].port = FD_PORT_FREE;
652         }
653
654         return 0;
655 }
656
657
658 int
659 rte_netmap_init_port(uint16_t portid, const struct rte_netmap_port_conf *conf)
660 {
661         int32_t ret;
662         uint16_t i;
663         uint16_t rx_slots, tx_slots;
664         struct rte_eth_rxconf rxq_conf;
665         struct rte_eth_txconf txq_conf;
666         struct rte_eth_dev_info dev_info;
667
668         if (conf == NULL ||
669                         portid >= RTE_DIM(ports) ||
670                         conf->nr_tx_rings > netmap.conf.max_rings ||
671                         conf->nr_rx_rings > netmap.conf.max_rings) {
672                 RTE_LOG(ERR, USER1, "%s(%u): invalid parameters\n",
673                         __func__, portid);
674                 return -EINVAL;
675         }
676
677         rx_slots = (uint16_t)rte_align32pow2(conf->nr_rx_slots);
678         tx_slots = (uint16_t)rte_align32pow2(conf->nr_tx_slots);
679
680         if (tx_slots > netmap.conf.max_slots ||
681                         rx_slots > netmap.conf.max_slots) {
682                 RTE_LOG(ERR, USER1, "%s(%u): invalid parameters\n",
683                         __func__, portid);
684                 return -EINVAL;
685         }
686
687         rte_eth_dev_info_get(portid, &dev_info);
688         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
689                 conf->eth_conf->txmode.offloads |=
690                         DEV_TX_OFFLOAD_MBUF_FAST_FREE;
691         ret = rte_eth_dev_configure(portid, conf->nr_rx_rings,
692                 conf->nr_tx_rings, conf->eth_conf);
693
694         if (ret < 0) {
695                 RTE_LOG(ERR, USER1, "Couldn't configure port %u\n", portid);
696                 return ret;
697         }
698
699         ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &rx_slots, &tx_slots);
700
701         if (ret < 0) {
702                 RTE_LOG(ERR, USER1,
703                         "Couldn't ot adjust number of descriptors for port %u\n",
704                         portid);
705                 return ret;
706         }
707
708         rxq_conf = dev_info.default_rxconf;
709         rxq_conf.offloads = conf->eth_conf->rxmode.offloads;
710         txq_conf = dev_info.default_txconf;
711         txq_conf.offloads = conf->eth_conf->txmode.offloads;
712         for (i = 0; i < conf->nr_tx_rings; i++) {
713                 ret = rte_eth_tx_queue_setup(portid, i, tx_slots,
714                         conf->socket_id, &txq_conf);
715
716                 if (ret < 0) {
717                         RTE_LOG(ERR, USER1,
718                                 "fail to configure TX queue %u of port %u\n",
719                                 i, portid);
720                         return ret;
721                 }
722
723                 ret = rte_eth_rx_queue_setup(portid, i, rx_slots,
724                         conf->socket_id, &rxq_conf, conf->pool);
725
726                 if (ret < 0) {
727                         RTE_LOG(ERR, USER1,
728                                 "fail to configure RX queue %u of port %u\n",
729                                 i, portid);
730                         return ret;
731                 }
732         }
733
734         /* copy config to the private storage. */
735         ports[portid].eth_conf = conf->eth_conf[0];
736         ports[portid].pool = conf->pool;
737         ports[portid].socket_id = conf->socket_id;
738         ports[portid].nr_tx_rings = conf->nr_tx_rings;
739         ports[portid].nr_rx_rings = conf->nr_rx_rings;
740         ports[portid].nr_tx_slots = tx_slots;
741         ports[portid].nr_rx_slots = rx_slots;
742         ports[portid].tx_burst = conf->tx_burst;
743         ports[portid].rx_burst = conf->rx_burst;
744
745         return 0;
746 }
747
748 int
749 rte_netmap_close(__rte_unused int fd)
750 {
751         int32_t rc;
752
753         rte_spinlock_lock(&netmap_lock);
754         rc = fd_release(fd);
755         rte_spinlock_unlock(&netmap_lock);
756
757         if (rc < 0) {
758                 errno =-rc;
759                 rc = -1;
760         }
761         return rc;
762 }
763
764 int rte_netmap_ioctl(int fd, uint32_t op, void *param)
765 {
766         int ret;
767
768         if (!FD_VALID(fd)) {
769             errno = EBADF;
770             return -1;
771         }
772
773         switch (op) {
774
775             case NIOCGINFO:
776                 ret = ioctl_niocginfo(fd, param);
777                 break;
778
779             case NIOCREGIF:
780                 ret = ioctl_niocregif(fd, param);
781                 break;
782
783             case NIOCUNREGIF:
784                 ret = ioctl_niocunregif(fd);
785                 break;
786
787             case NIOCRXSYNC:
788                 ret = ioctl_niocrxsync(fd);
789                 break;
790
791             case NIOCTXSYNC:
792                 ret = ioctl_nioctxsync(fd);
793                 break;
794
795             default:
796                 ret = -ENOTTY;
797         }
798
799         if (ret < 0) {
800                 errno = -ret;
801                 ret = -1;
802         } else {
803                 ret = 0;
804         }
805
806         return ret;
807 }
808
809 void *
810 rte_netmap_mmap(void *addr, size_t length,
811         int prot, int flags, int fd, off_t offset)
812 {
813         static const int cprot = PROT_WRITE | PROT_READ;
814
815         if (!FD_VALID(fd) || length + offset > netmap.mem_sz ||
816                         (prot & cprot) != cprot ||
817                         ((flags & MAP_FIXED) != 0 && addr != NULL)) {
818
819                 errno = EINVAL;
820                 return MAP_FAILED;
821         }
822
823         return (void *)((uintptr_t)netmap.mem + (uintptr_t)offset);
824 }
825
826 /**
827  * Return a "fake" file descriptor with a value above RLIMIT_NOFILE so that
828  * any attempt to use that file descriptor with the usual API will fail.
829  */
830 int
831 rte_netmap_open(__rte_unused const char *pathname, __rte_unused int flags)
832 {
833         int fd;
834
835         rte_spinlock_lock(&netmap_lock);
836         fd = fd_reserve();
837         rte_spinlock_unlock(&netmap_lock);
838
839         if (fd < 0) {
840                 errno = -fd;
841                 fd = -1;
842         }
843         return fd;
844 }
845
846 /**
847  * Doesn't support timeout other than 0 or infinite (negative) timeout
848  */
849 int
850 rte_netmap_poll(struct pollfd *fds, nfds_t nfds, int timeout)
851 {
852         int32_t count_it, ret;
853         uint32_t i, idx, port;
854         uint32_t want_rx, want_tx;
855
856         if (timeout > 0)
857                 return -1;
858
859         ret = 0;
860         do {
861                 for (i = 0; i < nfds; i++) {
862
863                         count_it = 0;
864
865                         if (!FD_VALID(fds[i].fd) || fds[i].events == 0) {
866                                 fds[i].revents = 0;
867                                 continue;
868                         }
869
870                         idx = FD_TO_IDX(fds[i].fd);
871                         if ((port = fd_port[idx].port) >= RTE_DIM(ports) ||
872                 ports[port].fd != idx) {
873
874                                 fds[i].revents |= POLLERR;
875                                 ret++;
876                                 continue;
877                         }
878
879                         want_rx = fds[i].events & (POLLIN  | POLLRDNORM);
880                         want_tx = fds[i].events & (POLLOUT | POLLWRNORM);
881
882                         if (want_rx && rx_sync_if(port) > 0) {
883                                 fds[i].revents = (uint16_t)
884                                         (fds[i].revents | want_rx);
885                                 count_it = 1;
886                         }
887                         if (want_tx && tx_sync_if(port) > 0) {
888                                 fds[i].revents = (uint16_t)
889                                         (fds[i].revents | want_tx);
890                                 count_it = 1;
891                         }
892
893                         ret += count_it;
894                 }
895         }
896         while ((ret == 0 && timeout < 0) || timeout);
897
898         return ret;
899 }