All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: "Michael S. Tsirkin" <mst@redhat.com>,
	qemu-devel@nongnu.org, Jason Wang <jasowang@redhat.com>,
	stefanha@linux.vnet.ibm.com, aurelien@aurel32.net
Subject: Re: [Qemu-devel] [PATCH 04/14] virtio-net: avoid sg copy
Date: Mon, 24 Sep 2012 19:37:40 -0500	[thread overview]
Message-ID: <87a9wf0wff.fsf@codemonkey.ws> (raw)
In-Reply-To: <04d3e68d5be34a87514a33fcd789339748d43cb5.1348527749.git.mst@redhat.com>

"Michael S. Tsirkin" <mst@redhat.com> writes:

> Avoid tweaking iovec during receive. This removes
> the need to copy the vector.
> Note: we already have an evil cast in work_around_broken_dhclient
> and unfortunately this adds another one.
> const on buf is ignored by this function anyway so arguably
> this is not making things much worse.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> ---
>  hw/virtio-net.c | 45 +++++++++++++++++++++------------------------
>  iov.h           |  8 ++++----
>  2 files changed, 25 insertions(+), 28 deletions(-)
>
> diff --git a/hw/virtio-net.c b/hw/virtio-net.c
> index 0c5081e..6e53858 100644
> --- a/hw/virtio-net.c
> +++ b/hw/virtio-net.c
> @@ -503,7 +503,7 @@ static int virtio_net_has_buffers(VirtIONet *n, int bufsize)
>   * we should provide a mechanism to disable it to avoid polluting the host
>   * cache.
>   */
> -static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
> +static void work_around_broken_dhclient(const struct virtio_net_hdr *hdr,
>                                          const uint8_t *buf, size_t size)
>  {
>      if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */
> @@ -513,31 +513,27 @@ static void work_around_broken_dhclient(struct virtio_net_hdr *hdr,
>          (buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */
>          /* FIXME this cast is evil */
>          net_checksum_calculate((uint8_t *)buf, size);
> -        hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
> +        ((struct virtio_net_hdr *)hdr)->flags &=
> ~VIRTIO_NET_HDR_F_NEEDS_CSUM;
>      }
>  }
>  
> -static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
> -                          const void *buf, size_t size, size_t hdr_len)
> +static int receive_header(VirtIONet *n, const struct iovec *iov, int iov_cnt,
> +                          const void *buf, size_t size)
>  {
> -    struct virtio_net_hdr *hdr = (struct virtio_net_hdr *)iov[0].iov_base;
>      int offset = 0;
>  
> -    hdr->flags = 0;
> -    hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
> -
>      if (n->has_vnet_hdr) {
> -        memcpy(hdr, buf, sizeof(*hdr));
> -        offset = sizeof(*hdr);
> -        work_around_broken_dhclient(hdr, buf + offset, size - offset);
> +        work_around_broken_dhclient(buf, buf + offset, size -
> offset);

I think it would be less ugly to cast here.

> +        offset = sizeof(struct virtio_net_hdr);
> +        iov_from_buf(iov, iov_cnt, 0, buf, offset);
> +    } else {
> +        struct virtio_net_hdr hdr = {
> +            .flags = 0,
> +            .gso_type = VIRTIO_NET_HDR_GSO_NONE
> +        };
> +        iov_from_buf(iov, iov_cnt, 0, &hdr, sizeof hdr);
>      }
>  
> -    /* We only ever receive a struct virtio_net_hdr from the tapfd,
> -     * but we may be passing along a larger header to the guest.
> -     */
> -    iov[0].iov_base += hdr_len;
> -    iov[0].iov_len  -= hdr_len;
> -
>      return offset;
>  }
>  
> @@ -598,7 +594,8 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
>  {
>      VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
>      struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL;
> -    size_t offset, i;
> +    const struct iovec *sg = elem.in_sg;
> +    size_t offset, i, guest_offset;
>  
>      if (!virtio_net_can_receive(&n->nic->nc))
>          return -1;
> @@ -615,7 +612,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
>      while (offset < size) {
>          VirtQueueElement elem;
>          int len, total;
> -        struct iovec sg[VIRTQUEUE_MAX_SIZE];
> +        const struct iovec *sg = elem.in_sg;
>  
>          total = 0;
>  
> @@ -640,20 +637,20 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
>              exit(1);
>          }
>  
> -        memcpy(&sg, &elem.in_sg[0], sizeof(sg[0]) * elem.in_num);
> -
>          if (i == 0) {
>              if (n->mergeable_rx_bufs)
>                  mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
>  
>              offset += receive_header(n, sg, elem.in_num,
> -                                     buf + offset, size - offset,
> -                                     n->guest_hdr_len);
> +                                     buf + offset, size - offset);
>              total += n->guest_hdr_len;
> +            guest_offset = n->guest_hdr_len;
> +        } else {
> +            guest_offset = 0;
>          }
>  
>          /* copy in packet.  ugh */
> -        len = iov_from_buf(sg, elem.in_num, 0,
> +        len = iov_from_buf(sg, elem.in_num, guest_offset,
>                             buf + offset, size - offset);
>          total += len;
>          offset += len;
> diff --git a/iov.h b/iov.h
> index f0daefa..6c9fdf1 100644
> --- a/iov.h
> +++ b/iov.h
> @@ -90,8 +90,8 @@ void iov_hexdump(const struct iovec *iov, const unsigned int iov_cnt,
>  /*
>   * Partial copy of vector from iov to dst_iov (data is not copied).
>   * dst_iov overlaps iov at a specified offset.
> - * size of dst_iov is at most bytes. Actual size is returned.
> + * size of dst_iov is at most bytes. dst vector count is returned.
>   */
> -size_t iov_cpy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
> -               const struct iovec *iov, unsigned int iov_cnt,
> -               size_t offset, size_t bytes);
> +unsigned iov_cpy(struct iovec *dst_iov, unsigned int dst_iov_cnt,
> +                 const struct iovec *iov, unsigned int iov_cnt,
> +                 size_t offset, size_t bytes);

I think this belongs in an earlier patch.

Regards,

Anthony Liguori

> -- 
> MST

  reply	other threads:[~2012-09-25  0:37 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-24 23:04 [Qemu-devel] [PATCH 00/14] virtio-net: iovec handling cleanup Michael S. Tsirkin
2012-09-24 23:04 ` [Qemu-devel] [PATCH 01/14] virtio-net: track host/guest header length Michael S. Tsirkin
2012-09-24 23:04 ` [Qemu-devel] [PATCH 02/14] iov: add const annotation Michael S. Tsirkin
2012-09-24 23:04 ` [Qemu-devel] [PATCH 03/14] iov: add iov_cpy Michael S. Tsirkin
2012-09-25  0:34   ` Anthony Liguori
2012-09-25  0:45     ` Michael S. Tsirkin
2012-09-24 23:04 ` [Qemu-devel] [PATCH 04/14] virtio-net: avoid sg copy Michael S. Tsirkin
2012-09-25  0:37   ` Anthony Liguori [this message]
2012-09-25  0:44     ` Michael S. Tsirkin
2012-09-24 23:04 ` [Qemu-devel] [PATCH 05/14] virtio-net: use safe iov operations for rx Michael S. Tsirkin
2012-09-25  0:38   ` Anthony Liguori
2012-09-24 23:04 ` [Qemu-devel] [PATCH 06/14] virtio-net: refactor receive_hdr Michael S. Tsirkin
2012-09-25  0:39   ` Anthony Liguori
2012-09-24 23:04 ` [Qemu-devel] [PATCH 07/14] virtio-net: first s/g is always at start of buf Michael S. Tsirkin
2012-09-25  0:39   ` Anthony Liguori
2012-09-24 23:04 ` [Qemu-devel] [PATCH 08/14] virtio-net: switch tx to safe iov functions Michael S. Tsirkin
2012-09-24 23:04 ` [Qemu-devel] [PATCH 09/14] virtio-net: simplify rx code Michael S. Tsirkin
2012-09-24 23:04 ` [Qemu-devel] [PATCH 10/14] virtio: don't mark unaccessed memory as dirty Michael S. Tsirkin
2012-09-24 23:05 ` [Qemu-devel] [PATCH 11/14] virtio-net: fix used len for tx Michael S. Tsirkin
2012-09-25  6:15   ` Jason Wang
2012-09-25  7:20     ` Michael S. Tsirkin
2012-09-24 23:05 ` [Qemu-devel] [PATCH 12/14] virtio-net: minor code simplification Michael S. Tsirkin
2012-09-24 23:05 ` [Qemu-devel] [PATCH 13/14] virtio-net: test peer header support at init time Michael S. Tsirkin
2012-09-24 23:05 ` [Qemu-devel] [PATCH 14/14] virtio-net: enable mrg buf header in tap on linux Michael S. Tsirkin

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=87a9wf0wff.fsf@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=aurelien@aurel32.net \
    --cc=jasowang@redhat.com \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@linux.vnet.ibm.com \
    /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.