No, you're right, nm_mmap() is not defined for all netmap versions. It will take a while for us to decide how to manage this. Would it be possible to go ahead with patch 1/2 only (I will reissue the patch series)?
Cheers, Vincenzo 2016-01-14 4:25 GMT+01:00 Jason Wang <jasow...@redhat.com>: > > > 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; > -- Vincenzo Maffione