All of lore.kernel.org
 help / color / mirror / Atom feed
From: Laurent Vivier <lvivier@redhat.com>
To: Greg Kurz <gkurz@linux.vnet.ibm.com>,
	"Michael S. Tsirkin" <mst@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities
Date: Tue, 12 Jan 2016 18:24:28 +0100	[thread overview]
Message-ID: <569536CC.5020405@redhat.com> (raw)
In-Reply-To: <20160111161202.17428.74331.stgit@bahia.huguette.org>



On 11/01/2016 17:12, Greg Kurz wrote:
> 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 (i.e. drivers sets the CONFIG_OK bit).
> If the backend cannot support the requested endiannes, we have to fallback
> onto virtio_net_hdr_swap(): this is recorded in the needs_vnet_hdr_swap flag,
> to be used in the TX and RX paths.
> 
> Note that we reset the backend to the default behaviour (guest native
> endianness) when the device stops (i.e. device status had CONFIG_OK bit and
> driver unsets it). This is needed, with the linux tap backend at least,
> otherwise the guest may loose network connectivity if rebooted into a
> different endianness.
> 
> The current vhost-net code also tries to configure net backends. This will
> be no more needed and will be reverted in a subsequent patch.
> 
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> ---
> v2:
> - dropped useless check in the 'else if' branch in virtio_net_vnet_status()
> - merged virtio_net_vhost_status() change from patch 2
> - use semicolon in "backend does no support..." error message
> - merged patch 3 (drop the virtio_needs_swap() helper)
> - provided some more details in changelog and comments
> ---
>  hw/net/virtio-net.c               |   49 +++++++++++++++++++++++++++++++++++--
>  include/hw/virtio/virtio-access.h |    9 -------
>  include/hw/virtio/virtio-net.h    |    1 +
>  3 files changed, 48 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index a877614e3e7a..497fb7119a08 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -128,6 +128,13 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
>      if (!n->vhost_started) {
>          int r, i;
>  
> +        if (n->needs_vnet_hdr_swap) {
> +            error_report("backend does not support %s vnet headers; "
> +                         "falling back on userspace virtio",
> +                         virtio_is_big_endian(vdev) ? "BE" : "LE");
> +            return;
> +        }
> +
>          /* Any packets outstanding? Purge them to avoid touching rings
>           * when vhost is running.
>           */
> @@ -152,6 +159,40 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
>      }
>  }
>  
> +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;
> +
> +        /* Before using the device, we tell the network backend about the
> +         * endianness to use when parsing vnet headers. If the backend can't
> +         * do it, we fallback onto fixing the headers in the core virtio-net
> +         * code.
> +         */
> +        if (virtio_is_big_endian(vdev)) {
> +            r = qemu_set_vnet_be(peer, true);
> +        } else {
> +            r = qemu_set_vnet_le(peer, true);
> +        }

If endianess of the guest and the virtio device is the same, but r is <
0 (-ENOSYS or -EINVAL) you will badly swap header (and disable vhost).

I think you need something like this to fall back to the old method:

        if (r < 0) {
#ifdef HOST_WORDS_BIGENDIAN
            r = virtio_access_is_big_endian(vdev) ? false : true;
#else
            r = virtio_access_is_big_endian(vdev) ? true : false;
#endif
        }


But...

> +        n->needs_vnet_hdr_swap = !!r;
> +    } else if (virtio_net_started(n, vdev->status)) {
> +        /* After using the device, we need to reset the network backend to
> +         * the default (guest native endianness), otherwise the guest may
> +         * loose network connectivity if it is rebooted into a different
> +         * endianness.
> +         */
> +        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 +200,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 +999,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 (n->needs_vnet_hdr_swap) {
> +            virtio_net_hdr_swap(VIRTIO_DEVICE(n), wbuf);
> +        }

... this will change the behavior here, as before it was not
conditional. Why ?

>          iov_from_buf(iov, iov_cnt, 0, buf, sizeof(struct virtio_net_hdr));
>      } else {
>          struct virtio_net_hdr hdr = {
> @@ -1167,7 +1212,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
>                  error_report("virtio-net header incorrect");
>                  exit(1);
>              }
> -            if (virtio_needs_swap(vdev)) {
> +            if (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-access.h b/include/hw/virtio/virtio-access.h
> index 8aec843c8ff3..a01fff2e51d7 100644
> --- a/include/hw/virtio/virtio-access.h
> +++ b/include/hw/virtio/virtio-access.h
> @@ -143,15 +143,6 @@ static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr)
>      }
>  }
>  
> -static inline bool virtio_needs_swap(VirtIODevice *vdev)
> -{
> -#ifdef HOST_WORDS_BIGENDIAN
> -    return virtio_access_is_big_endian(vdev) ? false : true;
> -#else
> -    return virtio_access_is_big_endian(vdev) ? true : false;
> -#endif
> -}
> -
>  static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s)
>  {
>  #ifdef HOST_WORDS_BIGENDIAN
> 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,
> 
> 

  parent reply	other threads:[~2016-01-12 17:24 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-11 16:11 [Qemu-devel] [PATCH v2 0/5] virtio/vhost cross-endian cleanup Greg Kurz
2016-01-11 16:12 ` [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities Greg Kurz
2016-01-11 18:16   ` Cornelia Huck
2016-01-12  0:32   ` Laurent Vivier
2016-01-12 17:24   ` Laurent Vivier [this message]
2016-01-13  9:06     ` Greg Kurz
2016-01-13  9:53       ` Laurent Vivier
2016-01-13 10:18         ` Greg Kurz
2016-01-11 16:12 ` [Qemu-devel] [PATCH v2 2/5] Revert "vhost-net: tell tap backend about the vnet endianness" Greg Kurz
2016-01-12  0:32   ` Laurent Vivier
2016-01-11 16:13 ` [Qemu-devel] [PATCH v2 3/5] virtio: move cross-endian helper to vhost Greg Kurz
2016-01-12  0:33   ` Laurent Vivier
2016-01-11 16:13 ` [Qemu-devel] [PATCH v2 4/5] vhost: move virtio 1.0 check to cross-endian helper Greg Kurz
2016-01-12  0:23   ` Laurent Vivier
2016-01-12 10:12     ` Greg Kurz
2016-01-11 16:18 ` [Qemu-devel] [PATCH v2 5/5] virtio: optimize virtio_access_is_big_endian() for little-endian targets Greg Kurz
2016-01-11 18:18   ` Cornelia Huck
2016-01-12  0:33   ` Laurent Vivier
  -- strict thread matches above, loose matches on Subject: below --
2016-01-11 16:02 [Qemu-devel] [PATCH v2 0/5] virtio/vhost cross-endian cleanup Greg Kurz
2016-01-11 16:02 ` [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities Greg Kurz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=569536CC.5020405@redhat.com \
    --to=lvivier@redhat.com \
    --cc=gkurz@linux.vnet.ibm.com \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.