Re: [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities

2016-01-13 Thread Greg Kurz
On Wed, 13 Jan 2016 10:53:11 +0100
Laurent Vivier  wrote:

> On 13/01/2016 10:06, Greg Kurz wrote:
> > On Tue, 12 Jan 2016 18:24:28 +0100
> > Laurent Vivier  wrote:
> >   
> >> 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 
> >>> ---
> >>> 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).
> >>  
> > 
> > This can only happen if the endianness of the host is not the same as the  
> 
> OK, you're right, I was studying sources without commit:
> 
> 052bd52 net: don't set native endianness
> 
> Sorry for the noise...
> 

No problem. Thank you again for your time !


> > endianness of the device. In this case (we usually call cross-endian) the
> > vnet headers must be byteswapped but the backend cannot handle it. This
> > has two consequences:
> > - vhost cannot be used since it requires the backend to support cross-endian
> >   vnet headers, so we fallback onto full emulation in QEMU
> > - the emulation code must byteswap vnet headers
> >   
> >> 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...
> >>  
> >

Re: [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities

2016-01-13 Thread Laurent Vivier


On 13/01/2016 10:06, Greg Kurz wrote:
> On Tue, 12 Jan 2016 18:24:28 +0100
> Laurent Vivier  wrote:
> 
>> 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 
>>> ---
>>> 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).
>>
> 
> This can only happen if the endianness of the host is not the same as the

OK, you're right, I was studying sources without commit:

052bd52 net: don't set native endianness

Sorry for the noise...

> endianness of the device. In this case (we usually call cross-endian) the
> vnet headers must be byteswapped but the backend cannot handle it. This
> has two consequences:
> - vhost cannot be used since it requires the backend to support cross-endian
>   vnet headers, so we fallback onto full emulation in QEMU
> - the emulation code must byteswap vnet headers
> 
>> 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.
>>> +

Re: [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities

2016-01-13 Thread Greg Kurz
On Tue, 12 Jan 2016 18:24:28 +0100
Laurent Vivier  wrote:

> 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 
> > ---
> > 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).
> 

This can only happen if the endianness of the host is not the same as the
endianness of the device. In this case (we usually call cross-endian) the
vnet headers must be byteswapped but the backend cannot handle it. This
has two consequences:
- vhost cannot be used since it requires the backend to support cross-endian
  vnet headers, so we fallback onto full emulation in QEMU
- the emulation code must byteswap vnet headers

> 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);
> > +}
> > +}
>

Re: [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities

2016-01-12 Thread Laurent Vivier


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 
> ---
> 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_swa

Re: [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities

2016-01-11 Thread Laurent Vivier


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 
> ---
> 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);
> +}
> +
> +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);
> +}
>  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");
>  

Re: [Qemu-devel] [PATCH v2 1/5] virtio-net: use the backend cross-endian capabilities

2016-01-11 Thread Cornelia Huck
On Mon, 11 Jan 2016 17:12:21 +0100
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

s/loose/lose/

> 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 

(...)

> +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);
> +}
> +
> +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

here again

> + * endianness.
> + */
> +if (virtio_is_big_endian(vdev)) {
> +qemu_set_vnet_be(peer, false);
> +} else {
> +qemu_set_vnet_le(peer, false);
> +}
> +}
> +}
> +

Reviewed-by: Cornelia Huck