From patchwork Thu Oct 29 03:12:27 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Scott Tsai X-Patchwork-Id: 56397 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n9T3CT4i007211 for ; Thu, 29 Oct 2009 03:12:29 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753911AbZJ2DMW (ORCPT ); Wed, 28 Oct 2009 23:12:22 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754216AbZJ2DMW (ORCPT ); Wed, 28 Oct 2009 23:12:22 -0400 Received: from mail-gx0-f216.google.com ([209.85.217.216]:54759 "EHLO mail-gx0-f216.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752299AbZJ2DMV (ORCPT ); Wed, 28 Oct 2009 23:12:21 -0400 Received: by gxk8 with SMTP id 8so1767137gxk.1 for ; Wed, 28 Oct 2009 20:12:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:content-type:cc:subject:from :to:in-reply-to:references:date:message-id:user-agent :content-transfer-encoding; bh=rkTxcocmMpB2zmPq2gY18/23nHubgHfmU8zpsV3fc6s=; b=jDCiwKu2kOoV2bUHhGvMCIAtRuh8+tOmw5v5XZSLBO8A4hq60YH7QHSpMnW4DF7kT6 f7vWG/1GAoWHRwPHs5YbVwPU/chHsSFGiYCuYlGVluowANrEUxq8ydbdKrvv/N0uNaoQ GMbiZ29Y82VH51f7eH2uE27dsj+fWs7iq6Pkc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=content-type:cc:subject:from:to:in-reply-to:references:date :message-id:user-agent:content-transfer-encoding; b=u+LVTo9157PoyMxL/63afjI6QnHTke3Pv8elnNyerjXavCf6ghXs1vxUA/KVUUxL1D gQO4l6fVtWZ0dekicVdcozDqeHwXFmrnx7AIO+QJFjklSqcKaIgeCr1/EMJ97sW0AGPB InoxeOvcgcnCvN1Cyh7OP8P4jkVSrYL4yvwJQ= Received: by 10.90.23.3 with SMTP id 3mr2999564agw.106.1256785946238; Wed, 28 Oct 2009 20:12:26 -0700 (PDT) Received: from localhost (220-136-176-197.dynamic.hinet.net [220.136.176.197]) by mx.google.com with ESMTPS id 6sm717973yxg.66.2009.10.28.20.12.24 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 28 Oct 2009 20:12:25 -0700 (PDT) Cc: qemu-devel , kvm , Anthony Liguori Subject: Re: [Qemu-devel] qemu-kvm-0.11 regression, crashes on older guests with virtio network From: Scott Tsai To: Dustin Kirkland In-reply-to: References: Date: Thu, 29 Oct 2009 11:12:27 +0800 Message-Id: <1256785636-sup-215@xpc65.scottt> User-Agent: Sup/0.9 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff --git a/hw/virtio-net.c b/hw/virtio-net.c index ce8e6cb..2e6725b 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -502,6 +502,8 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) return 0; } +int buffer_fits_in_virtqueue_top(VirtQueue *vq, int size); + static ssize_t virtio_net_receive2(VLANClientState *vc, const uint8_t *buf, size_t size, int raw) { VirtIONet *n = vc->opaque; @@ -518,6 +520,10 @@ static ssize_t virtio_net_receive2(VLANClientState *vc, const uint8_t *buf, size hdr_len = n->mergeable_rx_bufs ? sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); + /* drop packet instead of truncating it */ + if (!n->mergeable_rx_bufs && !buffer_fits_in_virtqueue_top(n->rx_vq, hdr_len + size)) + return; + offset = i = 0; while (offset < size) { @@ -531,7 +537,7 @@ static ssize_t virtio_net_receive2(VLANClientState *vc, const uint8_t *buf, size virtqueue_pop(n->rx_vq, &elem) == 0) { if (i == 0) return -1; - fprintf(stderr, "virtio-net truncating packet\n"); + fprintf(stderr, "virtio-net truncating packet: mergable_rx_bufs: %d\n", n->mergeable_rx_bufs); exit(1); } diff --git a/hw/virtio.c b/hw/virtio.c index 41e7ca2..d6f5a12 100644 --- a/hw/virtio.c +++ b/hw/virtio.c @@ -356,6 +356,28 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) return 0; } +/* buffer_fits_in_virtqueue_top: returns true if a 'size' byte buffer could fit in the + * input descriptors that virtqueue_pop() would have returned + */ +int buffer_fits_in_virtqueue_top(VirtQueue *vq, int size); + +int buffer_fits_in_virtqueue_top(VirtQueue *vq, int size) +{ + unsigned int i; + int input_iov_len_sum; + + if (!virtqueue_num_heads(vq, vq->last_avail_idx)) + return 0; + + input_iov_len_sum = 0; + i = virtqueue_get_head(vq, vq->last_avail_idx); + do { + if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) + input_iov_len_sum += vring_desc_len(vq, i); + } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num); + return input_iov_len_sum >= size; +} + int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) { unsigned int i, head, max;