Revision e35e23f6

b/hw/virtio-net.c
41 41
    int32_t tx_burst;
42 42
    int tx_waiting;
43 43
    uint32_t has_vnet_hdr;
44
    size_t host_hdr_len;
45
    size_t guest_hdr_len;
44 46
    uint8_t has_ufo;
45 47
    struct {
46 48
        VirtQueueElement elem;
......
231 233

  
232 234
    if (peer_has_vnet_hdr(n)) {
233 235
        tap_using_vnet_hdr(n->nic->nc.peer, 1);
236
        n->host_hdr_len = sizeof(struct virtio_net_hdr);
234 237
    } else {
235 238
        features &= ~(0x1 << VIRTIO_NET_F_CSUM);
236 239
        features &= ~(0x1 << VIRTIO_NET_F_HOST_TSO4);
......
278 281
    VirtIONet *n = to_virtio_net(vdev);
279 282

  
280 283
    n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF));
284
    n->guest_hdr_len = n->mergeable_rx_bufs ?
285
        sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
281 286

  
282 287
    if (n->has_vnet_hdr) {
283 288
        tap_set_offload(n->nic->nc.peer,
......
593 598
{
594 599
    VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
595 600
    struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL;
596
    size_t guest_hdr_len, offset, i, host_hdr_len;
601
    size_t offset, i;
597 602

  
598 603
    if (!virtio_net_can_receive(&n->nic->nc))
599 604
        return -1;
600 605

  
601 606
    /* hdr_len refers to the header we supply to the guest */
602
    guest_hdr_len = n->mergeable_rx_bufs ?
603
        sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
604

  
605

  
606
    host_hdr_len = n->has_vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
607
    if (!virtio_net_has_buffers(n, size + guest_hdr_len - host_hdr_len))
607
    if (!virtio_net_has_buffers(n, size + n->guest_hdr_len - n->host_hdr_len))
608 608
        return 0;
609 609

  
610 610
    if (!receive_filter(n, buf, size))
......
626 626
                    "i %zd mergeable %d offset %zd, size %zd, "
627 627
                    "guest hdr len %zd, host hdr len %zd guest features 0x%x",
628 628
                    i, n->mergeable_rx_bufs, offset, size,
629
                    guest_hdr_len, host_hdr_len, n->vdev.guest_features);
629
                    n->guest_hdr_len, n->host_hdr_len, n->vdev.guest_features);
630 630
            exit(1);
631 631
        }
632 632

  
......
635 635
            exit(1);
636 636
        }
637 637

  
638
        if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != guest_hdr_len) {
638
        if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != n->guest_hdr_len) {
639 639
            error_report("virtio-net header not in first element");
640 640
            exit(1);
641 641
        }
......
647 647
                mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
648 648

  
649 649
            offset += receive_header(n, sg, elem.in_num,
650
                                     buf + offset, size - offset, guest_hdr_len);
651
            total += guest_hdr_len;
650
                                     buf + offset, size - offset,
651
                                     n->guest_hdr_len);
652
            total += n->guest_hdr_len;
652 653
        }
653 654

  
654 655
        /* copy in packet.  ugh */
......
665 666
                         "i %zd mergeable %d offset %zd, size %zd, "
666 667
                         "guest hdr len %zd, host hdr len %zd",
667 668
                         i, n->mergeable_rx_bufs,
668
                         offset, size, guest_hdr_len, host_hdr_len);
669
                         offset, size, n->guest_hdr_len, n->host_hdr_len);
669 670
#endif
670 671
            return size;
671 672
        }
......
900 901
    qemu_get_buffer(f, n->mac, ETH_ALEN);
901 902
    n->tx_waiting = qemu_get_be32(f);
902 903
    n->mergeable_rx_bufs = qemu_get_be32(f);
904
    n->guest_hdr_len = n->mergeable_rx_bufs ?
905
        sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
903 906

  
904 907
    if (version_id >= 3)
905 908
        n->status = qemu_get_be16(f);
......
940 943

  
941 944
        if (n->has_vnet_hdr) {
942 945
            tap_using_vnet_hdr(n->nic->nc.peer, 1);
946
            n->host_hdr_len = sizeof(struct virtio_net_hdr);
943 947
            tap_set_offload(n->nic->nc.peer,
944 948
                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
945 949
                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
......
1044 1048
    n->tx_waiting = 0;
1045 1049
    n->tx_burst = net->txburst;
1046 1050
    n->mergeable_rx_bufs = 0;
1051
    n->guest_hdr_len = sizeof(struct virtio_net_hdr);
1047 1052
    n->promisc = 1; /* for compatibility */
1048 1053

  
1049 1054
    n->mac_table.macs = g_malloc0(MAC_TABLE_ENTRIES * ETH_ALEN);

Also available in: Unified diff