On 01/08/2016 09:15 PM, Vincenzo Maffione wrote: > With this patch, nm_open() does not mmap() the netmap device. This > operation is performed separately only if the memory area of the > port just opened was not known before. > A global list of netmap clients is kept to check when matches > occur. > > Signed-off-by: Vincenzo Maffione <v.maffi...@gmail.com> > --- > net/netmap.c | 38 +++++++++++++++++++++++++++++++++++++- > 1 file changed, 37 insertions(+), 1 deletion(-) > > diff --git a/net/netmap.c b/net/netmap.c > index 27295ab..6a4c01c 100644 > --- a/net/netmap.c > +++ b/net/netmap.c > @@ -49,8 +49,12 @@ typedef struct NetmapState { > bool write_poll; > struct iovec iov[IOV_MAX]; > int vnet_hdr_len; /* Current virtio-net header length. > */ > + QTAILQ_ENTRY(NetmapState) next; > } NetmapState; > > +static QTAILQ_HEAD(, NetmapState) netmap_clients = > + QTAILQ_HEAD_INITIALIZER(netmap_clients); > + > #ifndef __FreeBSD__ > #define pkt_copy bcopy > #else > @@ -78,6 +82,23 @@ pkt_copy(const void *_src, void *_dst, int l) > #endif /* __FreeBSD__ */ > > /* > + * find nm_desc parent with same allocator > + */ > +static struct nm_desc * > +netmap_find_memory(struct nm_desc *nmd) > +{ > + NetmapState *s; > + > + QTAILQ_FOREACH(s, &netmap_clients, next) { > + if (nmd->req.nr_arg2 == s->nmd->req.nr_arg2) { > + return s->nmd; > + } > + } > + > + return NULL; > +} > + > +/* > * Open a netmap device. We assume there is only one queue > * (which is the case for the VALE bridge). > */ > @@ -86,10 +107,11 @@ static struct nm_desc *netmap_open(const > NetdevNetmapOptions *nm_opts, > { > struct nm_desc *nmd; > struct nmreq req; > + int ret; > > memset(&req, 0, sizeof(req)); > > - nmd = nm_open(nm_opts->ifname, &req, NETMAP_NO_TX_POLL, > + nmd = nm_open(nm_opts->ifname, &req, NETMAP_NO_TX_POLL | NM_OPEN_NO_MMAP, > NULL); > if (nmd == NULL) { > error_setg_errno(errp, errno, "Failed to nm_open() %s", > @@ -97,6 +119,17 @@ static struct nm_desc *netmap_open(const > NetdevNetmapOptions *nm_opts, > return NULL; > } > > + /* Check if we already have a nm_desc that uses the same memory as the > one > + * just opened, so that nm_mmap() can skip mmap() and inherit from > parent. > + */ > + ret = nm_mmap(nmd, netmap_find_memory(nmd));
Looks like I could not find nm_mmap() definition in neither qemu or freebsd source. Is there anything missed? > + if (ret) { > + error_setg_errno(errp, errno, "Failed to nm_mmap() %s", > + nm_opts->ifname); > + nm_close(nmd); > + return NULL; > + } > + > return nmd; > } > > @@ -321,6 +354,8 @@ static void netmap_cleanup(NetClientState *nc) > netmap_poll(nc, false); > nm_close(s->nmd); > s->nmd = NULL; > + > + QTAILQ_REMOVE(&netmap_clients, s, next); > } > > /* Offloading manipulation support callbacks. */ > @@ -423,6 +458,7 @@ int net_init_netmap(const NetClientOptions *opts, > s->rx = NETMAP_RXRING(nmd->nifp, 0); > s->vnet_hdr_len = 0; > pstrcpy(s->ifname, sizeof(s->ifname), netmap_opts->ifname); > + QTAILQ_INSERT_TAIL(&netmap_clients, s, next); > netmap_read_poll(s, true); /* Initially only poll for reads. */ > > return 0;