xref: /openbmc/qemu/net/netmap.c (revision 131e744a15c54f0bad3d3925eeca1acf47996e06)
158952137SVincenzo Maffione /*
258952137SVincenzo Maffione  * netmap access for qemu
358952137SVincenzo Maffione  *
458952137SVincenzo Maffione  * Copyright (c) 2012-2013 Luigi Rizzo
558952137SVincenzo Maffione  *
658952137SVincenzo Maffione  * Permission is hereby granted, free of charge, to any person obtaining a copy
758952137SVincenzo Maffione  * of this software and associated documentation files (the "Software"), to deal
858952137SVincenzo Maffione  * in the Software without restriction, including without limitation the rights
958952137SVincenzo Maffione  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1058952137SVincenzo Maffione  * copies of the Software, and to permit persons to whom the Software is
1158952137SVincenzo Maffione  * furnished to do so, subject to the following conditions:
1258952137SVincenzo Maffione  *
1358952137SVincenzo Maffione  * The above copyright notice and this permission notice shall be included in
1458952137SVincenzo Maffione  * all copies or substantial portions of the Software.
1558952137SVincenzo Maffione  *
1658952137SVincenzo Maffione  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1758952137SVincenzo Maffione  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1858952137SVincenzo Maffione  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1958952137SVincenzo Maffione  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2058952137SVincenzo Maffione  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2158952137SVincenzo Maffione  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2258952137SVincenzo Maffione  * THE SOFTWARE.
2358952137SVincenzo Maffione  */
2458952137SVincenzo Maffione 
2558952137SVincenzo Maffione 
2658952137SVincenzo Maffione #include <sys/ioctl.h>
2758952137SVincenzo Maffione #include <net/if.h>
2858952137SVincenzo Maffione #include <sys/mman.h>
2958952137SVincenzo Maffione #include <stdint.h>
300a985b37SVincenzo Maffione #include <stdio.h>
310a985b37SVincenzo Maffione #define NETMAP_WITH_LIBS
3258952137SVincenzo Maffione #include <net/netmap.h>
3358952137SVincenzo Maffione #include <net/netmap_user.h>
3458952137SVincenzo Maffione 
3558952137SVincenzo Maffione #include "net/net.h"
36f6c65bfbSVincenzo Maffione #include "net/tap.h"
3758952137SVincenzo Maffione #include "clients.h"
3858952137SVincenzo Maffione #include "sysemu/sysemu.h"
3958952137SVincenzo Maffione #include "qemu/error-report.h"
4058952137SVincenzo Maffione #include "qemu/iov.h"
4158952137SVincenzo Maffione 
4258952137SVincenzo Maffione /* Private netmap device info. */
4358952137SVincenzo Maffione typedef struct NetmapPriv {
4458952137SVincenzo Maffione     int                 fd;
4558952137SVincenzo Maffione     size_t              memsize;
4658952137SVincenzo Maffione     void                *mem;
4758952137SVincenzo Maffione     struct netmap_if    *nifp;
4858952137SVincenzo Maffione     struct netmap_ring  *rx;
4958952137SVincenzo Maffione     struct netmap_ring  *tx;
5058952137SVincenzo Maffione     char                fdname[PATH_MAX];        /* Normally "/dev/netmap". */
5158952137SVincenzo Maffione     char                ifname[IFNAMSIZ];
5258952137SVincenzo Maffione } NetmapPriv;
5358952137SVincenzo Maffione 
5458952137SVincenzo Maffione typedef struct NetmapState {
5558952137SVincenzo Maffione     NetClientState      nc;
5658952137SVincenzo Maffione     NetmapPriv          me;
5758952137SVincenzo Maffione     bool                read_poll;
5858952137SVincenzo Maffione     bool                write_poll;
5958952137SVincenzo Maffione     struct iovec        iov[IOV_MAX];
60f6c65bfbSVincenzo Maffione     int                 vnet_hdr_len;  /* Current virtio-net header length. */
6158952137SVincenzo Maffione } NetmapState;
6258952137SVincenzo Maffione 
6358952137SVincenzo Maffione #ifndef __FreeBSD__
6458952137SVincenzo Maffione #define pkt_copy bcopy
6558952137SVincenzo Maffione #else
6658952137SVincenzo Maffione /* A fast copy routine only for multiples of 64 bytes, non overlapped. */
6758952137SVincenzo Maffione static inline void
6858952137SVincenzo Maffione pkt_copy(const void *_src, void *_dst, int l)
6958952137SVincenzo Maffione {
7058952137SVincenzo Maffione     const uint64_t *src = _src;
7158952137SVincenzo Maffione     uint64_t *dst = _dst;
7258952137SVincenzo Maffione     if (unlikely(l >= 1024)) {
7358952137SVincenzo Maffione         bcopy(src, dst, l);
7458952137SVincenzo Maffione         return;
7558952137SVincenzo Maffione     }
7658952137SVincenzo Maffione     for (; l > 0; l -= 64) {
7758952137SVincenzo Maffione         *dst++ = *src++;
7858952137SVincenzo Maffione         *dst++ = *src++;
7958952137SVincenzo Maffione         *dst++ = *src++;
8058952137SVincenzo Maffione         *dst++ = *src++;
8158952137SVincenzo Maffione         *dst++ = *src++;
8258952137SVincenzo Maffione         *dst++ = *src++;
8358952137SVincenzo Maffione         *dst++ = *src++;
8458952137SVincenzo Maffione         *dst++ = *src++;
8558952137SVincenzo Maffione     }
8658952137SVincenzo Maffione }
8758952137SVincenzo Maffione #endif /* __FreeBSD__ */
8858952137SVincenzo Maffione 
8958952137SVincenzo Maffione /*
9058952137SVincenzo Maffione  * Open a netmap device. We assume there is only one queue
9158952137SVincenzo Maffione  * (which is the case for the VALE bridge).
9258952137SVincenzo Maffione  */
9358952137SVincenzo Maffione static int netmap_open(NetmapPriv *me)
9458952137SVincenzo Maffione {
9558952137SVincenzo Maffione     int fd;
9658952137SVincenzo Maffione     int err;
9758952137SVincenzo Maffione     size_t l;
9858952137SVincenzo Maffione     struct nmreq req;
9958952137SVincenzo Maffione 
10058952137SVincenzo Maffione     me->fd = fd = open(me->fdname, O_RDWR);
10158952137SVincenzo Maffione     if (fd < 0) {
10258952137SVincenzo Maffione         error_report("Unable to open netmap device '%s' (%s)",
10358952137SVincenzo Maffione                         me->fdname, strerror(errno));
10458952137SVincenzo Maffione         return -1;
10558952137SVincenzo Maffione     }
10658952137SVincenzo Maffione     memset(&req, 0, sizeof(req));
10758952137SVincenzo Maffione     pstrcpy(req.nr_name, sizeof(req.nr_name), me->ifname);
10858952137SVincenzo Maffione     req.nr_ringid = NETMAP_NO_TX_POLL;
10958952137SVincenzo Maffione     req.nr_version = NETMAP_API;
11058952137SVincenzo Maffione     err = ioctl(fd, NIOCREGIF, &req);
11158952137SVincenzo Maffione     if (err) {
11258952137SVincenzo Maffione         error_report("Unable to register %s: %s", me->ifname, strerror(errno));
11358952137SVincenzo Maffione         goto error;
11458952137SVincenzo Maffione     }
11558952137SVincenzo Maffione     l = me->memsize = req.nr_memsize;
11658952137SVincenzo Maffione 
11758952137SVincenzo Maffione     me->mem = mmap(0, l, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
11858952137SVincenzo Maffione     if (me->mem == MAP_FAILED) {
11958952137SVincenzo Maffione         error_report("Unable to mmap netmap shared memory: %s",
12058952137SVincenzo Maffione                         strerror(errno));
12158952137SVincenzo Maffione         me->mem = NULL;
12258952137SVincenzo Maffione         goto error;
12358952137SVincenzo Maffione     }
12458952137SVincenzo Maffione 
12558952137SVincenzo Maffione     me->nifp = NETMAP_IF(me->mem, req.nr_offset);
12658952137SVincenzo Maffione     me->tx = NETMAP_TXRING(me->nifp, 0);
12758952137SVincenzo Maffione     me->rx = NETMAP_RXRING(me->nifp, 0);
12858952137SVincenzo Maffione     return 0;
12958952137SVincenzo Maffione 
13058952137SVincenzo Maffione error:
13158952137SVincenzo Maffione     close(me->fd);
13258952137SVincenzo Maffione     return -1;
13358952137SVincenzo Maffione }
13458952137SVincenzo Maffione 
13558952137SVincenzo Maffione /* Tell the event-loop if the netmap backend can send packets
13658952137SVincenzo Maffione    to the frontend. */
13758952137SVincenzo Maffione static int netmap_can_send(void *opaque)
13858952137SVincenzo Maffione {
13958952137SVincenzo Maffione     NetmapState *s = opaque;
14058952137SVincenzo Maffione 
14158952137SVincenzo Maffione     return qemu_can_send_packet(&s->nc);
14258952137SVincenzo Maffione }
14358952137SVincenzo Maffione 
14458952137SVincenzo Maffione static void netmap_send(void *opaque);
14558952137SVincenzo Maffione static void netmap_writable(void *opaque);
14658952137SVincenzo Maffione 
14758952137SVincenzo Maffione /* Set the event-loop handlers for the netmap backend. */
14858952137SVincenzo Maffione static void netmap_update_fd_handler(NetmapState *s)
14958952137SVincenzo Maffione {
15058952137SVincenzo Maffione     qemu_set_fd_handler2(s->me.fd,
15158952137SVincenzo Maffione                          s->read_poll  ? netmap_can_send : NULL,
15258952137SVincenzo Maffione                          s->read_poll  ? netmap_send     : NULL,
15358952137SVincenzo Maffione                          s->write_poll ? netmap_writable : NULL,
15458952137SVincenzo Maffione                          s);
15558952137SVincenzo Maffione }
15658952137SVincenzo Maffione 
15758952137SVincenzo Maffione /* Update the read handler. */
15858952137SVincenzo Maffione static void netmap_read_poll(NetmapState *s, bool enable)
15958952137SVincenzo Maffione {
16058952137SVincenzo Maffione     if (s->read_poll != enable) { /* Do nothing if not changed. */
16158952137SVincenzo Maffione         s->read_poll = enable;
16258952137SVincenzo Maffione         netmap_update_fd_handler(s);
16358952137SVincenzo Maffione     }
16458952137SVincenzo Maffione }
16558952137SVincenzo Maffione 
16658952137SVincenzo Maffione /* Update the write handler. */
16758952137SVincenzo Maffione static void netmap_write_poll(NetmapState *s, bool enable)
16858952137SVincenzo Maffione {
16958952137SVincenzo Maffione     if (s->write_poll != enable) {
17058952137SVincenzo Maffione         s->write_poll = enable;
17158952137SVincenzo Maffione         netmap_update_fd_handler(s);
17258952137SVincenzo Maffione     }
17358952137SVincenzo Maffione }
17458952137SVincenzo Maffione 
17558952137SVincenzo Maffione static void netmap_poll(NetClientState *nc, bool enable)
17658952137SVincenzo Maffione {
17758952137SVincenzo Maffione     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
17858952137SVincenzo Maffione 
17958952137SVincenzo Maffione     if (s->read_poll != enable || s->write_poll != enable) {
180*131e744aSPrasad Joshi         s->write_poll = enable;
18158952137SVincenzo Maffione         s->read_poll  = enable;
18258952137SVincenzo Maffione         netmap_update_fd_handler(s);
18358952137SVincenzo Maffione     }
18458952137SVincenzo Maffione }
18558952137SVincenzo Maffione 
18658952137SVincenzo Maffione /*
18758952137SVincenzo Maffione  * The fd_write() callback, invoked if the fd is marked as
18858952137SVincenzo Maffione  * writable after a poll. Unregister the handler and flush any
18958952137SVincenzo Maffione  * buffered packets.
19058952137SVincenzo Maffione  */
19158952137SVincenzo Maffione static void netmap_writable(void *opaque)
19258952137SVincenzo Maffione {
19358952137SVincenzo Maffione     NetmapState *s = opaque;
19458952137SVincenzo Maffione 
19558952137SVincenzo Maffione     netmap_write_poll(s, false);
19658952137SVincenzo Maffione     qemu_flush_queued_packets(&s->nc);
19758952137SVincenzo Maffione }
19858952137SVincenzo Maffione 
19958952137SVincenzo Maffione static ssize_t netmap_receive(NetClientState *nc,
20058952137SVincenzo Maffione       const uint8_t *buf, size_t size)
20158952137SVincenzo Maffione {
20258952137SVincenzo Maffione     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
20358952137SVincenzo Maffione     struct netmap_ring *ring = s->me.tx;
20458952137SVincenzo Maffione     uint32_t i;
20558952137SVincenzo Maffione     uint32_t idx;
20658952137SVincenzo Maffione     uint8_t *dst;
20758952137SVincenzo Maffione 
20858952137SVincenzo Maffione     if (unlikely(!ring)) {
20958952137SVincenzo Maffione         /* Drop. */
21058952137SVincenzo Maffione         return size;
21158952137SVincenzo Maffione     }
21258952137SVincenzo Maffione 
21358952137SVincenzo Maffione     if (unlikely(size > ring->nr_buf_size)) {
21458952137SVincenzo Maffione         RD(5, "[netmap_receive] drop packet of size %d > %d\n",
21558952137SVincenzo Maffione                                     (int)size, ring->nr_buf_size);
21658952137SVincenzo Maffione         return size;
21758952137SVincenzo Maffione     }
21858952137SVincenzo Maffione 
2190a985b37SVincenzo Maffione     if (nm_ring_empty(ring)) {
22058952137SVincenzo Maffione         /* No available slots in the netmap TX ring. */
22158952137SVincenzo Maffione         netmap_write_poll(s, true);
22258952137SVincenzo Maffione         return 0;
22358952137SVincenzo Maffione     }
22458952137SVincenzo Maffione 
22558952137SVincenzo Maffione     i = ring->cur;
22658952137SVincenzo Maffione     idx = ring->slot[i].buf_idx;
22758952137SVincenzo Maffione     dst = (uint8_t *)NETMAP_BUF(ring, idx);
22858952137SVincenzo Maffione 
22958952137SVincenzo Maffione     ring->slot[i].len = size;
23058952137SVincenzo Maffione     ring->slot[i].flags = 0;
23158952137SVincenzo Maffione     pkt_copy(buf, dst, size);
2320a985b37SVincenzo Maffione     ring->cur = ring->head = nm_ring_next(ring, i);
23358952137SVincenzo Maffione     ioctl(s->me.fd, NIOCTXSYNC, NULL);
23458952137SVincenzo Maffione 
23558952137SVincenzo Maffione     return size;
23658952137SVincenzo Maffione }
23758952137SVincenzo Maffione 
23858952137SVincenzo Maffione static ssize_t netmap_receive_iov(NetClientState *nc,
23958952137SVincenzo Maffione                     const struct iovec *iov, int iovcnt)
24058952137SVincenzo Maffione {
24158952137SVincenzo Maffione     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
24258952137SVincenzo Maffione     struct netmap_ring *ring = s->me.tx;
24358952137SVincenzo Maffione     uint32_t last;
24458952137SVincenzo Maffione     uint32_t idx;
24558952137SVincenzo Maffione     uint8_t *dst;
24658952137SVincenzo Maffione     int j;
24758952137SVincenzo Maffione     uint32_t i;
24858952137SVincenzo Maffione 
24958952137SVincenzo Maffione     if (unlikely(!ring)) {
25058952137SVincenzo Maffione         /* Drop the packet. */
25158952137SVincenzo Maffione         return iov_size(iov, iovcnt);
25258952137SVincenzo Maffione     }
25358952137SVincenzo Maffione 
254f6c65bfbSVincenzo Maffione     last = i = ring->cur;
25558952137SVincenzo Maffione 
2560a985b37SVincenzo Maffione     if (nm_ring_space(ring) < iovcnt) {
25758952137SVincenzo Maffione         /* Not enough netmap slots. */
25858952137SVincenzo Maffione         netmap_write_poll(s, true);
25958952137SVincenzo Maffione         return 0;
26058952137SVincenzo Maffione     }
26158952137SVincenzo Maffione 
26258952137SVincenzo Maffione     for (j = 0; j < iovcnt; j++) {
26358952137SVincenzo Maffione         int iov_frag_size = iov[j].iov_len;
26458952137SVincenzo Maffione         int offset = 0;
26558952137SVincenzo Maffione         int nm_frag_size;
26658952137SVincenzo Maffione 
26758952137SVincenzo Maffione         /* Split each iovec fragment over more netmap slots, if
26858952137SVincenzo Maffione            necessary. */
26958952137SVincenzo Maffione         while (iov_frag_size) {
27058952137SVincenzo Maffione             nm_frag_size = MIN(iov_frag_size, ring->nr_buf_size);
27158952137SVincenzo Maffione 
2720a985b37SVincenzo Maffione             if (unlikely(nm_ring_empty(ring))) {
27358952137SVincenzo Maffione                 /* We run out of netmap slots while splitting the
27458952137SVincenzo Maffione                    iovec fragments. */
27558952137SVincenzo Maffione                 netmap_write_poll(s, true);
27658952137SVincenzo Maffione                 return 0;
27758952137SVincenzo Maffione             }
27858952137SVincenzo Maffione 
27958952137SVincenzo Maffione             idx = ring->slot[i].buf_idx;
28058952137SVincenzo Maffione             dst = (uint8_t *)NETMAP_BUF(ring, idx);
28158952137SVincenzo Maffione 
28258952137SVincenzo Maffione             ring->slot[i].len = nm_frag_size;
28358952137SVincenzo Maffione             ring->slot[i].flags = NS_MOREFRAG;
28458952137SVincenzo Maffione             pkt_copy(iov[j].iov_base + offset, dst, nm_frag_size);
28558952137SVincenzo Maffione 
28658952137SVincenzo Maffione             last = i;
2870a985b37SVincenzo Maffione             i = nm_ring_next(ring, i);
28858952137SVincenzo Maffione 
28958952137SVincenzo Maffione             offset += nm_frag_size;
29058952137SVincenzo Maffione             iov_frag_size -= nm_frag_size;
29158952137SVincenzo Maffione         }
29258952137SVincenzo Maffione     }
29358952137SVincenzo Maffione     /* The last slot must not have NS_MOREFRAG set. */
29458952137SVincenzo Maffione     ring->slot[last].flags &= ~NS_MOREFRAG;
29558952137SVincenzo Maffione 
2960a985b37SVincenzo Maffione     /* Now update ring->cur and ring->head. */
2970a985b37SVincenzo Maffione     ring->cur = ring->head = i;
29858952137SVincenzo Maffione 
29958952137SVincenzo Maffione     ioctl(s->me.fd, NIOCTXSYNC, NULL);
30058952137SVincenzo Maffione 
30158952137SVincenzo Maffione     return iov_size(iov, iovcnt);
30258952137SVincenzo Maffione }
30358952137SVincenzo Maffione 
30458952137SVincenzo Maffione /* Complete a previous send (backend --> guest) and enable the
30558952137SVincenzo Maffione    fd_read callback. */
30658952137SVincenzo Maffione static void netmap_send_completed(NetClientState *nc, ssize_t len)
30758952137SVincenzo Maffione {
30858952137SVincenzo Maffione     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
30958952137SVincenzo Maffione 
31058952137SVincenzo Maffione     netmap_read_poll(s, true);
31158952137SVincenzo Maffione }
31258952137SVincenzo Maffione 
31358952137SVincenzo Maffione static void netmap_send(void *opaque)
31458952137SVincenzo Maffione {
31558952137SVincenzo Maffione     NetmapState *s = opaque;
31658952137SVincenzo Maffione     struct netmap_ring *ring = s->me.rx;
31758952137SVincenzo Maffione 
31858952137SVincenzo Maffione     /* Keep sending while there are available packets into the netmap
31958952137SVincenzo Maffione        RX ring and the forwarding path towards the peer is open. */
3200a985b37SVincenzo Maffione     while (!nm_ring_empty(ring) && qemu_can_send_packet(&s->nc)) {
32158952137SVincenzo Maffione         uint32_t i;
32258952137SVincenzo Maffione         uint32_t idx;
32358952137SVincenzo Maffione         bool morefrag;
32458952137SVincenzo Maffione         int iovcnt = 0;
32558952137SVincenzo Maffione         int iovsize;
32658952137SVincenzo Maffione 
32758952137SVincenzo Maffione         do {
32858952137SVincenzo Maffione             i = ring->cur;
32958952137SVincenzo Maffione             idx = ring->slot[i].buf_idx;
33058952137SVincenzo Maffione             morefrag = (ring->slot[i].flags & NS_MOREFRAG);
33158952137SVincenzo Maffione             s->iov[iovcnt].iov_base = (u_char *)NETMAP_BUF(ring, idx);
33258952137SVincenzo Maffione             s->iov[iovcnt].iov_len = ring->slot[i].len;
33358952137SVincenzo Maffione             iovcnt++;
33458952137SVincenzo Maffione 
3350a985b37SVincenzo Maffione             ring->cur = ring->head = nm_ring_next(ring, i);
3360a985b37SVincenzo Maffione         } while (!nm_ring_empty(ring) && morefrag);
33758952137SVincenzo Maffione 
3380a985b37SVincenzo Maffione         if (unlikely(nm_ring_empty(ring) && morefrag)) {
33958952137SVincenzo Maffione             RD(5, "[netmap_send] ran out of slots, with a pending"
34058952137SVincenzo Maffione                    "incomplete packet\n");
34158952137SVincenzo Maffione         }
34258952137SVincenzo Maffione 
34358952137SVincenzo Maffione         iovsize = qemu_sendv_packet_async(&s->nc, s->iov, iovcnt,
34458952137SVincenzo Maffione                                             netmap_send_completed);
34558952137SVincenzo Maffione 
34658952137SVincenzo Maffione         if (iovsize == 0) {
34758952137SVincenzo Maffione             /* The peer does not receive anymore. Packet is queued, stop
34858952137SVincenzo Maffione              * reading from the backend until netmap_send_completed()
34958952137SVincenzo Maffione              */
35058952137SVincenzo Maffione             netmap_read_poll(s, false);
35158952137SVincenzo Maffione             break;
35258952137SVincenzo Maffione         }
35358952137SVincenzo Maffione     }
35458952137SVincenzo Maffione }
35558952137SVincenzo Maffione 
35658952137SVincenzo Maffione /* Flush and close. */
35758952137SVincenzo Maffione static void netmap_cleanup(NetClientState *nc)
35858952137SVincenzo Maffione {
35958952137SVincenzo Maffione     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
36058952137SVincenzo Maffione 
36158952137SVincenzo Maffione     qemu_purge_queued_packets(nc);
36258952137SVincenzo Maffione 
36358952137SVincenzo Maffione     netmap_poll(nc, false);
36458952137SVincenzo Maffione     munmap(s->me.mem, s->me.memsize);
36558952137SVincenzo Maffione     close(s->me.fd);
36658952137SVincenzo Maffione 
36758952137SVincenzo Maffione     s->me.fd = -1;
36858952137SVincenzo Maffione }
36958952137SVincenzo Maffione 
370f6c65bfbSVincenzo Maffione /* Offloading manipulation support callbacks. */
371f6c65bfbSVincenzo Maffione static bool netmap_has_ufo(NetClientState *nc)
372f6c65bfbSVincenzo Maffione {
373f6c65bfbSVincenzo Maffione     return true;
374f6c65bfbSVincenzo Maffione }
375f6c65bfbSVincenzo Maffione 
376f6c65bfbSVincenzo Maffione static bool netmap_has_vnet_hdr(NetClientState *nc)
377f6c65bfbSVincenzo Maffione {
378f6c65bfbSVincenzo Maffione     return true;
379f6c65bfbSVincenzo Maffione }
380f6c65bfbSVincenzo Maffione 
381f6c65bfbSVincenzo Maffione static bool netmap_has_vnet_hdr_len(NetClientState *nc, int len)
382f6c65bfbSVincenzo Maffione {
383f6c65bfbSVincenzo Maffione     return len == 0 || len == sizeof(struct virtio_net_hdr) ||
384f6c65bfbSVincenzo Maffione                 len == sizeof(struct virtio_net_hdr_mrg_rxbuf);
385f6c65bfbSVincenzo Maffione }
386f6c65bfbSVincenzo Maffione 
387f6c65bfbSVincenzo Maffione static void netmap_using_vnet_hdr(NetClientState *nc, bool enable)
388f6c65bfbSVincenzo Maffione {
389f6c65bfbSVincenzo Maffione }
390f6c65bfbSVincenzo Maffione 
391f6c65bfbSVincenzo Maffione static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
392f6c65bfbSVincenzo Maffione {
393f6c65bfbSVincenzo Maffione     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
394f6c65bfbSVincenzo Maffione     int err;
395f6c65bfbSVincenzo Maffione     struct nmreq req;
396f6c65bfbSVincenzo Maffione 
397f6c65bfbSVincenzo Maffione     /* Issue a NETMAP_BDG_VNET_HDR command to change the virtio-net header
398f6c65bfbSVincenzo Maffione      * length for the netmap adapter associated to 'me->ifname'.
399f6c65bfbSVincenzo Maffione      */
400f6c65bfbSVincenzo Maffione     memset(&req, 0, sizeof(req));
401f6c65bfbSVincenzo Maffione     pstrcpy(req.nr_name, sizeof(req.nr_name), s->me.ifname);
402f6c65bfbSVincenzo Maffione     req.nr_version = NETMAP_API;
403f6c65bfbSVincenzo Maffione     req.nr_cmd = NETMAP_BDG_VNET_HDR;
404f6c65bfbSVincenzo Maffione     req.nr_arg1 = len;
405f6c65bfbSVincenzo Maffione     err = ioctl(s->me.fd, NIOCREGIF, &req);
406f6c65bfbSVincenzo Maffione     if (err) {
407f6c65bfbSVincenzo Maffione         error_report("Unable to execute NETMAP_BDG_VNET_HDR on %s: %s",
408f6c65bfbSVincenzo Maffione                      s->me.ifname, strerror(errno));
409f6c65bfbSVincenzo Maffione     } else {
410f6c65bfbSVincenzo Maffione         /* Keep track of the current length. */
411f6c65bfbSVincenzo Maffione         s->vnet_hdr_len = len;
412f6c65bfbSVincenzo Maffione     }
413f6c65bfbSVincenzo Maffione }
414f6c65bfbSVincenzo Maffione 
415f6c65bfbSVincenzo Maffione static void netmap_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
416f6c65bfbSVincenzo Maffione                                int ecn, int ufo)
417f6c65bfbSVincenzo Maffione {
418f6c65bfbSVincenzo Maffione     NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
419f6c65bfbSVincenzo Maffione 
420f6c65bfbSVincenzo Maffione     /* Setting a virtio-net header length greater than zero automatically
421f6c65bfbSVincenzo Maffione      * enables the offloadings.
422f6c65bfbSVincenzo Maffione      */
423f6c65bfbSVincenzo Maffione     if (!s->vnet_hdr_len) {
424f6c65bfbSVincenzo Maffione         netmap_set_vnet_hdr_len(nc, sizeof(struct virtio_net_hdr));
425f6c65bfbSVincenzo Maffione     }
426f6c65bfbSVincenzo Maffione }
42758952137SVincenzo Maffione 
42858952137SVincenzo Maffione /* NetClientInfo methods */
42958952137SVincenzo Maffione static NetClientInfo net_netmap_info = {
43058952137SVincenzo Maffione     .type = NET_CLIENT_OPTIONS_KIND_NETMAP,
43158952137SVincenzo Maffione     .size = sizeof(NetmapState),
43258952137SVincenzo Maffione     .receive = netmap_receive,
43358952137SVincenzo Maffione     .receive_iov = netmap_receive_iov,
43458952137SVincenzo Maffione     .poll = netmap_poll,
43558952137SVincenzo Maffione     .cleanup = netmap_cleanup,
436f6c65bfbSVincenzo Maffione     .has_ufo = netmap_has_ufo,
437f6c65bfbSVincenzo Maffione     .has_vnet_hdr = netmap_has_vnet_hdr,
438f6c65bfbSVincenzo Maffione     .has_vnet_hdr_len = netmap_has_vnet_hdr_len,
439f6c65bfbSVincenzo Maffione     .using_vnet_hdr = netmap_using_vnet_hdr,
440f6c65bfbSVincenzo Maffione     .set_offload = netmap_set_offload,
441f6c65bfbSVincenzo Maffione     .set_vnet_hdr_len = netmap_set_vnet_hdr_len,
44258952137SVincenzo Maffione };
44358952137SVincenzo Maffione 
44458952137SVincenzo Maffione /* The exported init function
44558952137SVincenzo Maffione  *
44658952137SVincenzo Maffione  * ... -net netmap,ifname="..."
44758952137SVincenzo Maffione  */
44858952137SVincenzo Maffione int net_init_netmap(const NetClientOptions *opts,
44958952137SVincenzo Maffione         const char *name, NetClientState *peer)
45058952137SVincenzo Maffione {
45158952137SVincenzo Maffione     const NetdevNetmapOptions *netmap_opts = opts->netmap;
45258952137SVincenzo Maffione     NetClientState *nc;
45358952137SVincenzo Maffione     NetmapPriv me;
45458952137SVincenzo Maffione     NetmapState *s;
45558952137SVincenzo Maffione 
45658952137SVincenzo Maffione     pstrcpy(me.fdname, sizeof(me.fdname),
45758952137SVincenzo Maffione         netmap_opts->has_devname ? netmap_opts->devname : "/dev/netmap");
45858952137SVincenzo Maffione     /* Set default name for the port if not supplied. */
45958952137SVincenzo Maffione     pstrcpy(me.ifname, sizeof(me.ifname), netmap_opts->ifname);
46058952137SVincenzo Maffione     if (netmap_open(&me)) {
46158952137SVincenzo Maffione         return -1;
46258952137SVincenzo Maffione     }
46358952137SVincenzo Maffione     /* Create the object. */
46458952137SVincenzo Maffione     nc = qemu_new_net_client(&net_netmap_info, peer, "netmap", name);
46558952137SVincenzo Maffione     s = DO_UPCAST(NetmapState, nc, nc);
46658952137SVincenzo Maffione     s->me = me;
467f6c65bfbSVincenzo Maffione     s->vnet_hdr_len = 0;
46858952137SVincenzo Maffione     netmap_read_poll(s, true); /* Initially only poll for reads. */
46958952137SVincenzo Maffione 
47058952137SVincenzo Maffione     return 0;
47158952137SVincenzo Maffione }
47258952137SVincenzo Maffione 
473