From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mark McLoughlin Subject: Re: [PATCH 08/12] kvm: qemu: Don't require all drivers to use virtio_net_hdr Date: Tue, 12 Aug 2008 18:41:05 +0100 Message-ID: <1218562865.29159.1.camel@muff> References: <1218485535-877-1-git-send-email-markmc@redhat.com> <1218485535-877-2-git-send-email-markmc@redhat.com> <1218485535-877-3-git-send-email-markmc@redhat.com> <1218485535-877-4-git-send-email-markmc@redhat.com> <1218485535-877-5-git-send-email-markmc@redhat.com> <1218485535-877-6-git-send-email-markmc@redhat.com> <1218485535-877-7-git-send-email-markmc@redhat.com> <1218485535-877-8-git-send-email-markmc@redhat.com> <1218485535-877-9-git-send-email-markmc@redhat.com> Reply-To: Mark McLoughlin Mime-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 7bit Cc: kvm@vger.kernel.org To: Avi Kivity Return-path: Received: from mx1.redhat.com ([66.187.233.31]:50402 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751303AbYHLRlZ (ORCPT ); Tue, 12 Aug 2008 13:41:25 -0400 In-Reply-To: <1218485535-877-9-git-send-email-markmc@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: Hi Avi, Thanks for catching the build error in this one. Here's a new (yet uglier) version; the rest remain the same. Cheers, Mark. Subject: [PATCH 08/11] kvm: qemu: Don't require all drivers to use virtio_net_hdr The virtio-net driver is the only one which wishes to deal with virtio_net_hdr headers, so add a "using_vnet_hdr" flag to allow it to indicate this. Preferably, we'd prefer to only enable IFF_VNET_HDR when we're using virtio-net, but qemu's various abstractions would make this very messy. Signed-off-by: Mark McLoughlin --- qemu/hw/virtio-net.c | 1 + qemu/net.h | 1 + qemu/vl.c | 87 +++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c index 9b1298e..2298316 100644 --- a/qemu/hw/virtio-net.c +++ b/qemu/hw/virtio-net.c @@ -97,6 +97,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) uint32_t features = (1 << VIRTIO_NET_F_MAC); if (tap_has_vnet_hdr(host)) { + tap_using_vnet_hdr(host, 1); features |= (1 << VIRTIO_NET_F_CSUM); features |= (1 << VIRTIO_NET_F_GUEST_CSUM); features |= (1 << VIRTIO_NET_F_GUEST_TSO4); diff --git a/qemu/net.h b/qemu/net.h index ae1a338..4891669 100644 --- a/qemu/net.h +++ b/qemu/net.h @@ -46,6 +46,7 @@ void qemu_handler_true(void *opaque); void do_info_network(void); int tap_has_vnet_hdr(void *opaque); +void tap_using_vnet_hdr(void *opaque, int using_vnet_hdr); int net_client_init(const char *device, const char *opts); void net_client_uninit(NICInfo *nd); diff --git a/qemu/vl.c b/qemu/vl.c index f5aacf0..63e21f2 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -4347,6 +4347,10 @@ int tap_has_vnet_hdr(void *opaque) return 0; } +void tap_using_vnet_hdr(void *opaque, int using_vnet_hdr) +{ +} + #else /* !defined(_WIN32) */ #ifndef IFF_VNET_HDR @@ -4367,10 +4371,11 @@ typedef struct TAPState { char buf[TAP_BUFSIZE]; int size; unsigned int has_vnet_hdr : 1; + unsigned int using_vnet_hdr : 1; } TAPState; -static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov, - int iovcnt) +static ssize_t tap_writev(void *opaque, const struct iovec *iov, + int iovcnt) { TAPState *s = opaque; ssize_t len; @@ -4382,17 +4387,51 @@ static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov, return len; } +static ssize_t tap_receive_iov(void *opaque, const struct iovec *iov, + int iovcnt) +{ +#ifdef IFF_VNET_HDR + TAPState *s = opaque; + + if (s->has_vnet_hdr && !s->using_vnet_hdr) { + struct iovec *iov_copy; + struct virtio_net_hdr hdr = { 0, }; + + iov_copy = alloca(sizeof(struct iovec) * (iovcnt + 1)); + + iov_copy[0].iov_base = &hdr; + iov_copy[0].iov_len = sizeof(hdr); + + memcpy(&iov_copy[1], iov, sizeof(struct iovec) * iovcnt); + + return tap_writev(opaque, iov_copy, iovcnt + 1); + } +#endif + + return tap_writev(opaque, iov, iovcnt); +} + static void tap_receive(void *opaque, const uint8_t *buf, int size) { + struct iovec iov[2]; + int i = 0; + +#ifdef IFF_VNET_HDR TAPState *s = opaque; - int ret; - for(;;) { - ret = write(s->fd, buf, size); - if (ret < 0 && (errno == EINTR || errno == EAGAIN)) { - } else { - break; - } + struct virtio_net_hdr hdr = { 0, }; + + if (s->has_vnet_hdr && !s->using_vnet_hdr) { + iov[i].iov_base = &hdr; + iov[i].iov_len = sizeof(hdr); + i++; } +#endif + + iov[i].iov_base = (char *) buf; + iov[i].iov_len = size; + i++; + + tap_writev(opaque, iov, i); } static int tap_can_send(void *opaque) @@ -4421,6 +4460,21 @@ static int tap_can_send(void *opaque) return can_receive; } +static int tap_send_packet(TAPState *s) +{ + uint8_t *buf = s->buf; + int size = s->size; + +#ifdef IFF_VNET_HDR + if (s->has_vnet_hdr && !s->using_vnet_hdr) { + buf += sizeof(struct virtio_net_hdr); + size -= sizeof(struct virtio_net_hdr); + } +#endif + + return qemu_send_packet(s->vc, buf, size); +} + static void tap_send(void *opaque) { TAPState *s = opaque; @@ -4430,7 +4484,7 @@ static void tap_send(void *opaque) int err; /* If noone can receive the packet, buffer it */ - err = qemu_send_packet(s->vc, s->buf, s->size); + err = tap_send_packet(s); if (err == -EAGAIN) return; } @@ -4454,7 +4508,7 @@ static void tap_send(void *opaque) int err; /* If noone can receive the packet, buffer it */ - err = qemu_send_packet(s->vc, s->buf, s->size); + err = tap_send_packet(s); if (err == -EAGAIN) break; } @@ -4469,6 +4523,17 @@ int tap_has_vnet_hdr(void *opaque) return s ? s->has_vnet_hdr : 0; } +void tap_using_vnet_hdr(void *opaque, int using_vnet_hdr) +{ + VLANClientState *vc = opaque; + TAPState *s = vc->opaque; + + if (!s || !s->has_vnet_hdr) + return; + + s->using_vnet_hdr = using_vnet_hdr != 0; +} + #ifdef TUNSETOFFLOAD static void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) -- 1.5.4.1