[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/2] net: netmap: avoid mmap() when ports use the sa
From: |
Vincenzo Maffione |
Subject: |
[Qemu-devel] [PATCH 2/2] net: netmap: avoid mmap() when ports use the same shared memory area |
Date: |
Fri, 8 Jan 2016 14:15:17 +0100 |
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 <address@hidden>
---
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));
+ 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;
--
2.7.0