Signed-off-by: Wei Xu <w...@redhat.com> --- hw/net/virtio-net.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 8da2815..1ca3dd5 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1630,6 +1630,18 @@ static int virtio_net_load_device(VirtIODevice *vdev, QEMUFile *f, return 0; } +static void virtio_net_rsc_ipv4_checksum(NetRscSeg *seg) +{ + uint32_t sum; + struct ip_header *ip; + + ip = (struct ip_header *)(seg->buf + IP_OFFSET); + + ip->ip_sum = 0; + sum = net_checksum_add_cont(sizeof(struct ip_header), (uint8_t *)ip, 0); + ip->ip_sum = cpu_to_be16(net_checksum_finish(sum)); +} + static void virtio_net_rsc_purge(void *opq) { int ret = 0; @@ -1643,6 +1655,10 @@ static void virtio_net_rsc_purge(void *opq) continue; } + if ((chain->proto == ETH_P_IP) && seg->is_coalesced) { + virtio_net_rsc_ipv4_checksum(seg); + } + ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size); QTAILQ_REMOVE(&chain->buffers, seg, next); g_free(seg->buf); @@ -1853,6 +1869,9 @@ static size_t virtio_net_rsc_callback(NetRscChain *chain, NetClientState *nc, QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) { ret = coalesce(chain, seg, buf, size); if (RSC_FINAL == ret) { + if ((chain->proto == ETH_P_IP) && seg->is_coalesced) { + virtio_net_rsc_ipv4_checksum(seg); + } ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size); QTAILQ_REMOVE(&chain->buffers, seg, next); g_free(seg->buf); -- 2.4.0