Message ID | b666d94d3251d0fc7da536fce47b8af2228cc896.1452258704.git.v.maffione@gmail.com |
---|---|
State | New |
Headers | show |
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.maffione@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;
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 <jasowang@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.maffione@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; >
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)); + 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;
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.maffione@gmail.com> --- net/netmap.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)