qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] tests/vhost-user-bridge: add scattering of inco


From: Michael S. Tsirkin
Subject: Re: [Qemu-devel] [PATCH] tests/vhost-user-bridge: add scattering of incoming packets
Date: Wed, 17 Feb 2016 15:35:46 +0200

On Wed, Feb 17, 2016 at 03:02:28PM +0200, Victor Kaplansky wrote:
> This patch adds to the vubr test the scattering of incoming
> packets to the chain of RX buffer.  Also, this patch corrects the
> size of the header preceding the packet in RX buffers.
> 
> Note that this patch doesn't add the support for mergeable
> buffers.
> 
> Signed-off-by: Victor Kaplansky <address@hidden>
> ---
>  tests/vhost-user-bridge.c | 95 
> +++++++++++++++++++++++++++++++----------------
>  1 file changed, 63 insertions(+), 32 deletions(-)
> 
> diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c
> index 9fb09f1d..7f746317 100644
> --- a/tests/vhost-user-bridge.c
> +++ b/tests/vhost-user-bridge.c
> @@ -47,6 +47,7 @@
>  #include <arpa/inet.h>
>  #include <ctype.h>
>  #include <netdb.h>
> +#include <qemu/osdep.h>
>  
>  #include <linux/vhost.h>
>  
> @@ -186,6 +187,8 @@ typedef struct VubrVirtq {
>  
>  #define VHOST_MEMORY_MAX_NREGIONS    8
>  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> +/* v1.0 compliant. */
> +#define VIRTIO_F_VERSION_1           32
>  
>  #define VHOST_LOG_PAGE 4096
>  
> @@ -294,6 +297,7 @@ typedef struct VubrDev {
>      struct sockaddr_in backend_udp_dest;
>      int ready;
>      uint64_t features;
> +    int hdrlen;
>  } VubrDev;
>  
>  static const char *vubr_request_str[] = {
> @@ -484,7 +488,8 @@ vubr_backend_udp_recvbuf(VubrDev *dev, uint8_t *buf, 
> size_t buflen)
>  static void
>  vubr_consume_raw_packet(VubrDev *dev, uint8_t *buf, uint32_t len)
>  {
> -    int hdrlen = sizeof(struct virtio_net_hdr_v1);
> +    int hdrlen = dev->hdrlen;
> +    DPRINT("    hdrlen = %d\n", dev->hdrlen);
>  
>      if (VHOST_USER_BRIDGE_DEBUG) {
>          print_buffer(buf, len);
> @@ -546,6 +551,7 @@ vubr_post_buffer(VubrDev *dev, VubrVirtq *vq, uint8_t 
> *buf, int32_t len)
>      struct vring_avail *avail = vq->avail;
>      struct vring_used *used = vq->used;
>      uint64_t log_guest_addr = vq->log_guest_addr;
> +    int32_t remained_len = len;
>  
>      unsigned int size = vq->size;
>  
> @@ -560,36 +566,49 @@ vubr_post_buffer(VubrDev *dev, VubrVirtq *vq, uint8_t 
> *buf, int32_t len)
>      uint16_t d_index = avail->ring[a_index];
>  
>      int i = d_index;
> +    uint32_t written_len = 0;
>  
> -    DPRINT("Post packet to guest on vq:\n");
> -    DPRINT("    size             = %d\n", vq->size);
> -    DPRINT("    last_avail_index = %d\n", vq->last_avail_index);
> -    DPRINT("    last_used_index  = %d\n", vq->last_used_index);
> -    DPRINT("    a_index = %d\n", a_index);
> -    DPRINT("    u_index = %d\n", u_index);
> -    DPRINT("    d_index = %d\n", d_index);
> -    DPRINT("    desc[%d].addr    = 0x%016"PRIx64"\n", i, desc[i].addr);
> -    DPRINT("    desc[%d].len     = %d\n", i, desc[i].len);
> -    DPRINT("    desc[%d].flags   = %d\n", i, desc[i].flags);
> -    DPRINT("    avail->idx = %d\n", avail_index);
> -    DPRINT("    used->idx  = %d\n", used->idx);
> -
> -    if (!(desc[i].flags & VRING_DESC_F_WRITE)) {
> -        /* FIXME: we should find writable descriptor. */
> -        fprintf(stderr, "Error: descriptor is not writable. Exiting.\n");
> -        exit(1);
> -    }
> +    do {
> +        DPRINT("Post packet to guest on vq:\n");
> +        DPRINT("    size             = %d\n", vq->size);
> +        DPRINT("    last_avail_index = %d\n", vq->last_avail_index);
> +        DPRINT("    last_used_index  = %d\n", vq->last_used_index);
> +        DPRINT("    a_index = %d\n", a_index);
> +        DPRINT("    u_index = %d\n", u_index);
> +        DPRINT("    d_index = %d\n", d_index);
> +        DPRINT("    desc[%d].addr    = 0x%016"PRIx64"\n", i, desc[i].addr);
> +        DPRINT("    desc[%d].len     = %d\n", i, desc[i].len);
> +        DPRINT("    desc[%d].flags   = %d\n", i, desc[i].flags);
> +        DPRINT("    avail->idx = %d\n", avail_index);
> +        DPRINT("    used->idx  = %d\n", used->idx);
> +
> +        if (!(desc[i].flags & VRING_DESC_F_WRITE)) {
> +            /* FIXME: we should find writable descriptor. */
> +            fprintf(stderr, "Error: descriptor is not writable. Exiting.\n");
> +            exit(1);
> +        }
>  
> -    void *chunk_start = (void *)gpa_to_va(dev, desc[i].addr);
> -    uint32_t chunk_len = desc[i].len;
> +        void *chunk_start = (void *)gpa_to_va(dev, desc[i].addr);
> +        uint32_t chunk_len = desc[i].len;
> +        uint32_t chunk_write_len = MIN(remained_len, chunk_len);
>  
> -    if (len <= chunk_len) {
> -        memcpy(chunk_start, buf, len);
> -        vubr_log_write(dev, desc[i].addr, len);
> -    } else {
> -        fprintf(stderr,
> -                "Received too long packet from the backend. Dropping...\n");
> -        return;
> +        memcpy(chunk_start, buf + written_len, chunk_write_len);
> +        vubr_log_write(dev, desc[i].addr, chunk_write_len);
> +        remained_len -= chunk_write_len;
> +        written_len += chunk_write_len;
> +
> +        if ((remained_len == 0) || !(desc[i].flags & VRING_DESC_F_NEXT)) {
> +            break;
> +        }
> +
> +        i = desc[i].next;
> +    } while (1);
> +
> +    if (remained_len > 0) {
> +            fprintf(stderr,
> +                    "Too long packet for RX, remained remained_len = %d, 
> Dropping...\n",
> +                    remained_len);

remained_len -> remaining_len?

> +            return;
>      }
>  
>      /* Add descriptor to the used ring. */
> @@ -697,7 +716,7 @@ vubr_backend_recv_cb(int sock, void *ctx)
>      VubrVirtq *rx_vq = &dev->vq[0];
>      uint8_t buf[4096];
>      struct virtio_net_hdr_v1 *hdr = (struct virtio_net_hdr_v1 *)buf;
> -    int hdrlen = sizeof(struct virtio_net_hdr_v1);
> +    int hdrlen = dev->hdrlen;
>      int buflen = sizeof(buf);
>      int len;
>  
> @@ -706,6 +725,7 @@ vubr_backend_recv_cb(int sock, void *ctx)
>      }
>  
>      DPRINT("\n\n   ***   IN UDP RECEIVE CALLBACK    ***\n\n");
> +    DPRINT("    hdrlen = %d\n", hdrlen);
>  
>      uint16_t avail_index = atomic_mb_read(&rx_vq->avail->idx);
>  
> @@ -717,10 +737,12 @@ vubr_backend_recv_cb(int sock, void *ctx)
>          return;
>      }
>  
> +    memset(buf, 0, hdrlen);
> +    /* TODO: support mergeable buffers. */
> +    if (hdrlen == 12)
> +        hdr->num_buffers = 1;
>      len = vubr_backend_udp_recvbuf(dev, buf + hdrlen, buflen - hdrlen);
>  
> -    *hdr = (struct virtio_net_hdr_v1) { };
> -    hdr->num_buffers = 1;
>      vubr_post_buffer(dev, rx_vq, buf, len + hdrlen);
>  }
>  
> @@ -754,7 +776,8 @@ vubr_get_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
>              ((1ULL << VIRTIO_NET_F_MRG_RXBUF) |
>               (1ULL << VHOST_F_LOG_ALL) |
>               (1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) |
> -             (1ULL << VHOST_USER_F_PROTOCOL_FEATURES));
> +             (1ULL << VHOST_USER_F_PROTOCOL_FEATURES) |
> +             (1ULL << VIRTIO_F_VERSION_1));
>  
>      vmsg->size = sizeof(vmsg->payload.u64);
>  

I'm not sure you should advertize VIRTIO_F_VERSION_1 as long as
you don't also do CPU to LE/LE to CPU transformations
when it's negotiated.


Also, you must advertize ANY_LAYOUT with VIRTIO_F_VERSION_1.

> @@ -768,7 +791,15 @@ static int
>  vubr_set_features_exec(VubrDev *dev, VhostUserMsg *vmsg)
>  {
>      DPRINT("u64: 0x%016"PRIx64"\n", vmsg->payload.u64);
> +
>      dev->features = vmsg->payload.u64;
> +    if ((dev->features & (1ULL << VIRTIO_F_VERSION_1)) ||
> +        (dev->features & (1ULL << VIRTIO_NET_F_MRG_RXBUF))) {
> +        dev->hdrlen = 12;
> +    } else {
> +        dev->hdrlen = 10;
> +    }
> +
>      return 0;
>  }
>  
> -- 
> Victor



reply via email to

[Prev in Thread] Current Thread [Next in Thread]