qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/3] vhost: mergeable buffer support
@ 2010-07-28 15:01 Michael S. Tsirkin
  2010-07-28 15:01 ` [Qemu-devel] [PATCH 1/3] tap: generalize code for different vnet header len Michael S. Tsirkin
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2010-07-28 15:01 UTC (permalink / raw)
  To: qemu-devel

This adds support for mergeable buffers with vhost.
The tun ioctl this relies on is already in 2.6.34,
the vhost support for the feature has been submitted
for 2.6.36.

Michael S. Tsirkin (3):
  tap: generalize code for different vnet header len
  tap: add APIs for vnet header length
  vhost_net: mergeable buffers support

 hw/vhost_net.c    |   24 +++++++++++++++++++++++-
 net/tap-aix.c     |    9 +++++++++
 net/tap-bsd.c     |    9 +++++++++
 net/tap-linux.c   |   29 +++++++++++++++++++++++++++++
 net/tap-linux.h   |    8 ++++++++
 net/tap-solaris.c |    9 +++++++++
 net/tap-win32.c   |    9 +++++++++
 net/tap.c         |   49 +++++++++++++++++++++++++++++++++++--------------
 net/tap.h         |    4 ++++
 9 files changed, 135 insertions(+), 15 deletions(-)

-- 
MST

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 1/3] tap: generalize code for different vnet header len
  2010-07-28 15:01 [Qemu-devel] [PATCH 0/3] vhost: mergeable buffer support Michael S. Tsirkin
@ 2010-07-28 15:01 ` Michael S. Tsirkin
  2010-07-28 15:01 ` [Qemu-devel] [PATCH 2/3] tap: add APIs for vnet header length Michael S. Tsirkin
  2010-07-28 15:01 ` [Qemu-devel] [PATCH 3/3] vhost_net: mergeable buffers support Michael S. Tsirkin
  2 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2010-07-28 15:01 UTC (permalink / raw)
  To: qemu-devel

Make host vnet header length a structure field in
preparation for using this support in linux kernel.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 net/tap-linux.h |    6 ++++++
 net/tap.c       |   28 ++++++++++++++--------------
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/net/tap-linux.h b/net/tap-linux.h
index 9f94358..727fcf5 100644
--- a/net/tap-linux.h
+++ b/net/tap-linux.h
@@ -52,4 +52,10 @@ struct virtio_net_hdr
     uint16_t csum_offset;
 };
 
+struct virtio_net_hdr_mrg_rxbuf
+{
+    struct virtio_net_hdr hdr;
+    uint16_t num_buffers;   /* Number of merged rx buffers */
+};
+
 #endif /* QEMU_TAP_H */
diff --git a/net/tap.c b/net/tap.c
index 0147dab..2866ff4 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -57,10 +57,10 @@ typedef struct TAPState {
     uint8_t buf[TAP_BUFSIZE];
     unsigned int read_poll : 1;
     unsigned int write_poll : 1;
-    unsigned int has_vnet_hdr : 1;
     unsigned int using_vnet_hdr : 1;
     unsigned int has_ufo: 1;
     VHostNetState *vhost_net;
+    unsigned host_vnet_hdr_len;
 } TAPState;
 
 static int launch_script(const char *setup_script, const char *ifname, int fd);
@@ -121,11 +121,11 @@ static ssize_t tap_receive_iov(VLANClientState *nc, const struct iovec *iov,
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
     const struct iovec *iovp = iov;
     struct iovec iov_copy[iovcnt + 1];
-    struct virtio_net_hdr hdr = { 0, };
+    struct virtio_net_hdr_mrg_rxbuf hdr = { };
 
-    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
+    if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
         iov_copy[0].iov_base = &hdr;
-        iov_copy[0].iov_len =  sizeof(hdr);
+        iov_copy[0].iov_len =  s->host_vnet_hdr_len;
         memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov));
         iovp = iov_copy;
         iovcnt++;
@@ -139,11 +139,11 @@ static ssize_t tap_receive_raw(VLANClientState *nc, const uint8_t *buf, size_t s
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
     struct iovec iov[2];
     int iovcnt = 0;
-    struct virtio_net_hdr hdr = { 0, };
+    struct virtio_net_hdr_mrg_rxbuf hdr = { };
 
-    if (s->has_vnet_hdr) {
+    if (s->host_vnet_hdr_len) {
         iov[iovcnt].iov_base = &hdr;
-        iov[iovcnt].iov_len  = sizeof(hdr);
+        iov[iovcnt].iov_len  = s->host_vnet_hdr_len;
         iovcnt++;
     }
 
@@ -159,7 +159,7 @@ static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
     struct iovec iov[1];
 
-    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
+    if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
         return tap_receive_raw(nc, buf, size);
     }
 
@@ -202,9 +202,9 @@ static void tap_send(void *opaque)
             break;
         }
 
-        if (s->has_vnet_hdr && !s->using_vnet_hdr) {
-            buf  += sizeof(struct virtio_net_hdr);
-            size -= sizeof(struct virtio_net_hdr);
+        if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
+            buf  += s->host_vnet_hdr_len;
+            size -= s->host_vnet_hdr_len;
         }
 
         size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed);
@@ -229,7 +229,7 @@ int tap_has_vnet_hdr(VLANClientState *nc)
 
     assert(nc->info->type == NET_CLIENT_TYPE_TAP);
 
-    return s->has_vnet_hdr;
+    return !!s->host_vnet_hdr_len;
 }
 
 void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr)
@@ -239,7 +239,7 @@ void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr)
     using_vnet_hdr = using_vnet_hdr != 0;
 
     assert(nc->info->type == NET_CLIENT_TYPE_TAP);
-    assert(s->has_vnet_hdr == using_vnet_hdr);
+    assert(!!s->host_vnet_hdr_len == using_vnet_hdr);
 
     s->using_vnet_hdr = using_vnet_hdr;
 }
@@ -310,7 +310,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
     s = DO_UPCAST(TAPState, nc, nc);
 
     s->fd = fd;
-    s->has_vnet_hdr = vnet_hdr != 0;
+    s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
     s->using_vnet_hdr = 0;
     s->has_ufo = tap_probe_has_ufo(s->fd);
     tap_set_offload(&s->nc, 0, 0, 0, 0, 0);
-- 
1.7.2.rc0.14.g41c1c

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 2/3] tap: add APIs for vnet header length
  2010-07-28 15:01 [Qemu-devel] [PATCH 0/3] vhost: mergeable buffer support Michael S. Tsirkin
  2010-07-28 15:01 ` [Qemu-devel] [PATCH 1/3] tap: generalize code for different vnet header len Michael S. Tsirkin
@ 2010-07-28 15:01 ` Michael S. Tsirkin
  2010-07-28 15:01 ` [Qemu-devel] [PATCH 3/3] vhost_net: mergeable buffers support Michael S. Tsirkin
  2 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2010-07-28 15:01 UTC (permalink / raw)
  To: qemu-devel

Add APIs to control host header length. First user
will be vhost-net.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 net/tap-aix.c     |    9 +++++++++
 net/tap-bsd.c     |    9 +++++++++
 net/tap-linux.c   |   29 +++++++++++++++++++++++++++++
 net/tap-linux.h   |    2 ++
 net/tap-solaris.c |    9 +++++++++
 net/tap-win32.c   |    9 +++++++++
 net/tap.c         |   21 +++++++++++++++++++++
 net/tap.h         |    4 ++++
 8 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/net/tap-aix.c b/net/tap-aix.c
index 4bc9f2f..e19aaba 100644
--- a/net/tap-aix.c
+++ b/net/tap-aix.c
@@ -46,6 +46,15 @@ int tap_probe_has_ufo(int fd)
     return 0;
 }
 
+int tap_probe_vnet_hdr_len(int fd, int len)
+{
+    return 0;
+}
+
+void tap_fd_set_vnet_hdr_len(int fd, int len)
+{
+}
+
 void tap_fd_set_offload(int fd, int csum, int tso4,
                         int tso6, int ecn, int ufo)
 {
diff --git a/net/tap-bsd.c b/net/tap-bsd.c
index 3773d5d..3513075 100644
--- a/net/tap-bsd.c
+++ b/net/tap-bsd.c
@@ -116,6 +116,15 @@ int tap_probe_has_ufo(int fd)
     return 0;
 }
 
+int tap_probe_vnet_hdr_len(int fd, int len)
+{
+    return 0;
+}
+
+void tap_fd_set_vnet_hdr_len(int fd, int len)
+{
+}
+
 void tap_fd_set_offload(int fd, int csum, int tso4,
                         int tso6, int ecn, int ufo)
 {
diff --git a/net/tap-linux.c b/net/tap-linux.c
index 03b8301..a425ff0 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -127,6 +127,35 @@ int tap_probe_has_ufo(int fd)
     return 1;
 }
 
+/* Verify that we can assign given length */
+int tap_probe_vnet_hdr_len(int fd, int len)
+{
+    int orig;
+    if (ioctl(fd, TUNGETVNETHDRSZ, &orig) == -1) {
+        return 0;
+    }
+    if (ioctl(fd, TUNSETVNETHDRSZ, &len) == -1) {
+        return 0;
+    }
+    /* Restore original length: we can't handle failure. */
+    if (ioctl(fd, TUNSETVNETHDRSZ, &orig) == -1) {
+        fprintf(stderr, "TUNGETVNETHDRSZ ioctl() failed: %s. Exiting.\n",
+                strerror(errno));
+        assert(0);
+        return -errno;
+    }
+    return 1;
+}
+
+void tap_fd_set_vnet_hdr_len(int fd, int len)
+{
+    if (ioctl(fd, TUNSETVNETHDRSZ, &len) == -1) {
+        fprintf(stderr, "TUNSETVNETHDRSZ ioctl() failed: %s. Exiting.\n",
+                strerror(errno));
+        assert(0);
+    }
+}
+
 void tap_fd_set_offload(int fd, int csum, int tso4,
                         int tso6, int ecn, int ufo)
 {
diff --git a/net/tap-linux.h b/net/tap-linux.h
index 727fcf5..659e981 100644
--- a/net/tap-linux.h
+++ b/net/tap-linux.h
@@ -27,6 +27,8 @@
 #define TUNSETOFFLOAD  _IOW('T', 208, unsigned int)
 #define TUNGETIFF      _IOR('T', 210, unsigned int)
 #define TUNSETSNDBUF   _IOW('T', 212, int)
+#define TUNGETVNETHDRSZ _IOR('T', 215, int)
+#define TUNSETVNETHDRSZ _IOW('T', 216, int)
 
 #endif
 
diff --git a/net/tap-solaris.c b/net/tap-solaris.c
index 50d127a..ca1d496 100644
--- a/net/tap-solaris.c
+++ b/net/tap-solaris.c
@@ -211,6 +211,15 @@ int tap_probe_has_ufo(int fd)
     return 0;
 }
 
+int tap_probe_vnet_hdr_len(int fd, int len)
+{
+    return 0;
+}
+
+void tap_fd_set_vnet_hdr_len(int fd, int len)
+{
+}
+
 void tap_fd_set_offload(int fd, int csum, int tso4,
                         int tso6, int ecn, int ufo)
 {
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 74348da..9fe4fcd 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -728,6 +728,15 @@ int tap_has_vnet_hdr(VLANClientState *vc)
     return 0;
 }
 
+int tap_probe_vnet_hdr_len(int fd, int len)
+{
+    return 0;
+}
+
+void tap_fd_set_vnet_hdr_len(int fd, int len)
+{
+}
+
 void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr)
 {
 }
diff --git a/net/tap.c b/net/tap.c
index 2866ff4..4afb314 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -232,6 +232,27 @@ int tap_has_vnet_hdr(VLANClientState *nc)
     return !!s->host_vnet_hdr_len;
 }
 
+int tap_has_vnet_hdr_len(VLANClientState *nc, int len)
+{
+    TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+    assert(nc->info->type == NET_CLIENT_TYPE_TAP);
+
+    return tap_probe_vnet_hdr_len(s->fd, len);
+}
+
+void tap_set_vnet_hdr_len(VLANClientState *nc, int len)
+{
+    TAPState *s = DO_UPCAST(TAPState, nc, nc);
+
+    assert(nc->info->type == NET_CLIENT_TYPE_TAP);
+    assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
+           len == sizeof(struct virtio_net_hdr));
+
+    tap_fd_set_vnet_hdr_len(s->fd, len);
+    s->host_vnet_hdr_len = len;
+}
+
 void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr)
 {
     TAPState *s = DO_UPCAST(TAPState, nc, nc);
diff --git a/net/tap.h b/net/tap.h
index b8cec83..e44bd2b 100644
--- a/net/tap.h
+++ b/net/tap.h
@@ -40,13 +40,17 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen);
 
 int tap_has_ufo(VLANClientState *vc);
 int tap_has_vnet_hdr(VLANClientState *vc);
+int tap_has_vnet_hdr_len(VLANClientState *vc, int len);
 void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr);
 void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn, int ufo);
+void tap_set_vnet_hdr_len(VLANClientState *vc, int len);
 
 int tap_set_sndbuf(int fd, QemuOpts *opts);
 int tap_probe_vnet_hdr(int fd);
+int tap_probe_vnet_hdr_len(int fd, int len);
 int tap_probe_has_ufo(int fd);
 void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo);
+void tap_fd_set_vnet_hdr_len(int fd, int len);
 
 int tap_get_fd(VLANClientState *vc);
 
-- 
1.7.2.rc0.14.g41c1c

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 3/3] vhost_net: mergeable buffers support
  2010-07-28 15:01 [Qemu-devel] [PATCH 0/3] vhost: mergeable buffer support Michael S. Tsirkin
  2010-07-28 15:01 ` [Qemu-devel] [PATCH 1/3] tap: generalize code for different vnet header len Michael S. Tsirkin
  2010-07-28 15:01 ` [Qemu-devel] [PATCH 2/3] tap: add APIs for vnet header length Michael S. Tsirkin
@ 2010-07-28 15:01 ` Michael S. Tsirkin
  2 siblings, 0 replies; 4+ messages in thread
From: Michael S. Tsirkin @ 2010-07-28 15:01 UTC (permalink / raw)
  To: qemu-devel

use the new tap APIs to set header length

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 hw/vhost_net.c |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index 606aa0c..3bd3aa6 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -51,7 +51,9 @@ unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
     if (!(net->dev.features & (1 << VIRTIO_RING_F_INDIRECT_DESC))) {
         features &= ~(1 << VIRTIO_RING_F_INDIRECT_DESC);
     }
-    features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+    if (!(net->dev.features & (1 << VIRTIO_NET_F_MRG_RXBUF))) {
+        features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+    }
     return features;
 }
 
@@ -64,6 +66,9 @@ void vhost_net_ack_features(struct vhost_net *net, unsigned features)
     if (features & (1 << VIRTIO_RING_F_INDIRECT_DESC)) {
         net->dev.acked_features |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
     }
+    if (features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
+        net->dev.acked_features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
+    }
 }
 
 static int vhost_net_get_fd(VLANClientState *backend)
@@ -98,6 +103,10 @@ struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
     if (r < 0) {
         goto fail;
     }
+    if (!tap_has_vnet_hdr_len(backend,
+                              sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
+        net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
+    }
     if (~net->dev.features & net->dev.backend_features) {
         fprintf(stderr, "vhost lacks feature mask %" PRIu64 " for backend\n",
                 (uint64_t)(~net->dev.features & net->dev.backend_features));
@@ -118,6 +127,10 @@ int vhost_net_start(struct vhost_net *net,
 {
     struct vhost_vring_file file = { };
     int r;
+    if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
+        tap_set_vnet_hdr_len(net->vc,
+                             sizeof(struct virtio_net_hdr_mrg_rxbuf));
+    }
 
     net->dev.nvqs = 2;
     net->dev.vqs = net->vqs;
@@ -145,6 +158,9 @@ fail:
     }
     net->vc->info->poll(net->vc, true);
     vhost_dev_stop(&net->dev, dev);
+    if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
+        tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr));
+    }
     return r;
 }
 
@@ -159,11 +175,17 @@ void vhost_net_stop(struct vhost_net *net,
     }
     net->vc->info->poll(net->vc, true);
     vhost_dev_stop(&net->dev, dev);
+    if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
+        tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr));
+    }
 }
 
 void vhost_net_cleanup(struct vhost_net *net)
 {
     vhost_dev_cleanup(&net->dev);
+    if (net->dev.acked_features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
+        tap_set_vnet_hdr_len(net->vc, sizeof(struct virtio_net_hdr));
+    }
     qemu_free(net);
 }
 #else
-- 
1.7.2.rc0.14.g41c1c

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-07-28 15:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-28 15:01 [Qemu-devel] [PATCH 0/3] vhost: mergeable buffer support Michael S. Tsirkin
2010-07-28 15:01 ` [Qemu-devel] [PATCH 1/3] tap: generalize code for different vnet header len Michael S. Tsirkin
2010-07-28 15:01 ` [Qemu-devel] [PATCH 2/3] tap: add APIs for vnet header length Michael S. Tsirkin
2010-07-28 15:01 ` [Qemu-devel] [PATCH 3/3] vhost_net: mergeable buffers support Michael S. Tsirkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).