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