From patchwork Fri Nov 6 17:45:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Greg Kurz X-Patchwork-Id: 541050 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id C00C514027C for ; Sat, 7 Nov 2015 04:46:02 +1100 (AEDT) Received: from localhost ([::1]:40244 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zul5M-00066n-TJ for incoming@patchwork.ozlabs.org; Fri, 06 Nov 2015 12:46:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44332) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zul4q-0005oa-Mj for qemu-devel@nongnu.org; Fri, 06 Nov 2015 12:45:34 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zul4l-0004iw-LX for qemu-devel@nongnu.org; Fri, 06 Nov 2015 12:45:28 -0500 Received: from e06smtp07.uk.ibm.com ([195.75.94.103]:51401) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zul4l-0004iT-D8 for qemu-devel@nongnu.org; Fri, 06 Nov 2015 12:45:23 -0500 Received: from localhost by e06smtp07.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 6 Nov 2015 17:45:19 -0000 Received: from d06dlp02.portsmouth.uk.ibm.com (9.149.20.14) by e06smtp07.uk.ibm.com (192.168.101.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 6 Nov 2015 17:45:07 -0000 X-IBM-Helo: d06dlp02.portsmouth.uk.ibm.com X-IBM-MailFrom: gkurz@linux.vnet.ibm.com X-IBM-RcptTo: qemu-devel@nongnu.org Received: from b06cxnps4075.portsmouth.uk.ibm.com (d06relay12.portsmouth.uk.ibm.com [9.149.109.197]) by d06dlp02.portsmouth.uk.ibm.com (Postfix) with ESMTP id 0DCA6219004D for ; Fri, 6 Nov 2015 17:45:03 +0000 (GMT) Received: from d06av01.portsmouth.uk.ibm.com (d06av01.portsmouth.uk.ibm.com [9.149.37.212]) by b06cxnps4075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id tA6Hj7dm57868432 for ; Fri, 6 Nov 2015 17:45:07 GMT Received: from d06av01.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av01.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id tA6Hj6b7001646 for ; Fri, 6 Nov 2015 10:45:06 -0700 Received: from smtp.lab.toulouse-stg.fr.ibm.com (srv01.lab.toulouse-stg.fr.ibm.com [9.101.4.1]) by d06av01.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id tA6Hj6WN001640; Fri, 6 Nov 2015 10:45:06 -0700 Received: from bahia.huguette.org (icon-9-164-143-167.megacenter.de.ibm.com [9.164.143.167]) by smtp.lab.toulouse-stg.fr.ibm.com (Postfix) with ESMTP id EBE26220052; Fri, 6 Nov 2015 18:45:05 +0100 (CET) From: Greg Kurz To: "Michael S. Tsirkin" Date: Fri, 06 Nov 2015 18:45:04 +0100 Message-ID: <20151106174504.7887.26798.stgit@bahia.huguette.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15110617-0029-0000-0000-000004C1B3D9 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 195.75.94.103 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH] virtio-net: use the backend cross-endian capabilities X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org When running a fully emulated device in cross-endian conditions, including a virtio 1.0 device offered to a big endian guest, we need to fix the vnet headers. This is currently handled by the virtio_net_hdr_swap() function in the core virtio-net code but it should actually be handled by the net backend. With this patch, virtio-net now tries to configure the backend to do the endian fixing when the device starts. If the backend cannot support the requested endiannes, we have to fall back on virtio_net_hdr_swap(): this is recorded in the needs_vnet_hdr_swap flag. Whether we have to fix vnet headers in userspace now depends on: virtio_needs_swap(vdev) && n->needs_vnet_hdr_swap virtio_needs_swap() allows to filter out non cross-endian cases without runtime penalty. The current vhost-net code also tries to configure net backends. This will be no more needed and will be addressed in a subsequent patch. Signed-off-by: Greg Kurz --- hw/net/virtio-net.c | 35 +++++++++++++++++++++++++++++++++-- include/hw/virtio/virtio-net.h | 1 + 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index a877614e3e7a..69dc4442e5e2 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -152,6 +152,33 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status) } } +static int peer_has_vnet_hdr(VirtIONet *n); + +static void virtio_net_vnet_status(VirtIONet *n, uint8_t status) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(n); + NetClientState *peer = qemu_get_queue(n->nic)->peer; + + if (virtio_net_started(n, status)) { + int r; + + if (virtio_is_big_endian(vdev)) { + r = qemu_set_vnet_be(peer, true); + } else { + r = qemu_set_vnet_le(peer, true); + } + + n->needs_vnet_hdr_swap = !!r; + } else if (virtio_net_started(n, vdev->status) && + !virtio_net_started(n, status)) { + if (virtio_is_big_endian(vdev)) { + qemu_set_vnet_be(peer, false); + } else { + qemu_set_vnet_le(peer, false); + } + } +} + static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status) { VirtIONet *n = VIRTIO_NET(vdev); @@ -159,6 +186,7 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status) int i; uint8_t queue_status; + virtio_net_vnet_status(n, status); virtio_net_vhost_status(n, status); for (i = 0; i < n->max_queues; i++) { @@ -957,7 +985,10 @@ static void receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt, void *wbuf = (void *)buf; work_around_broken_dhclient(wbuf, wbuf + n->host_hdr_len, size - n->host_hdr_len); - virtio_net_hdr_swap(VIRTIO_DEVICE(n), wbuf); + + if (virtio_needs_swap(vdev) && n->needs_vnet_hdr_swap) { + virtio_net_hdr_swap(VIRTIO_DEVICE(n), wbuf); + } iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr)); } else { struct virtio_net_hdr hdr = { @@ -1167,7 +1198,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) error_report("virtio-net header incorrect"); exit(1); } - if (virtio_needs_swap(vdev)) { + if (virtio_needs_swap(vdev) && n->needs_vnet_hdr_swap) { virtio_net_hdr_swap(vdev, (void *) &mhdr); sg2[0].iov_base = &mhdr; sg2[0].iov_len = n->guest_hdr_len; diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index f3cc25feca2b..27bc868fbc7d 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -94,6 +94,7 @@ typedef struct VirtIONet { uint64_t curr_guest_offloads; QEMUTimer *announce_timer; int announce_counter; + bool needs_vnet_hdr_swap; } VirtIONet; void virtio_net_set_netclient_name(VirtIONet *n, const char *name,