From patchwork Fri May 3 20:29:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sasha Levin X-Patchwork-Id: 2519321 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 5B4F13FD1A for ; Fri, 3 May 2013 20:30:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934282Ab3ECUaY (ORCPT ); Fri, 3 May 2013 16:30:24 -0400 Received: from userp1040.oracle.com ([156.151.31.81]:28911 "EHLO userp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933868Ab3ECUaX (ORCPT ); Fri, 3 May 2013 16:30:23 -0400 Received: from acsinet21.oracle.com (acsinet21.oracle.com [141.146.126.237]) by userp1040.oracle.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.1) with ESMTP id r43KUAOJ017813 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 3 May 2013 20:30:11 GMT Received: from aserz7021.oracle.com (aserz7021.oracle.com [141.146.126.230]) by acsinet21.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r43KU9vD001976 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Fri, 3 May 2013 20:30:09 GMT Received: from abhmt114.oracle.com (abhmt114.oracle.com [141.146.116.66]) by aserz7021.oracle.com (8.14.4+Sun/8.14.4) with ESMTP id r43KU9HO001965; Fri, 3 May 2013 20:30:09 GMT Received: from lappy.us.oracle.com (/10.159.134.53) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 03 May 2013 13:30:08 -0700 From: Sasha Levin To: penberg@kernel.org, asias@redhat.com Cc: kvm@vger.kernel.org, Sasha Levin Subject: [PATCH 8/8] kvm tools: virtio-net mergable rx buffers Date: Fri, 3 May 2013 16:29:17 -0400 Message-Id: <1367612957-6719-8-git-send-email-sasha.levin@oracle.com> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1367612957-6719-1-git-send-email-sasha.levin@oracle.com> References: <1367612957-6719-1-git-send-email-sasha.levin@oracle.com> X-Source-IP: acsinet21.oracle.com [141.146.126.237] Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Support mergable rx buffers for virtio-net. This helps reduce the amount of memory the guest kernel has to allocate per rx vq. Signed-off-by: Sasha Levin --- tools/kvm/include/kvm/uip.h | 2 +- tools/kvm/net/uip/core.c | 2 +- tools/kvm/virtio/net.c | 42 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h index cb79e94..4e63808 100644 --- a/tools/kvm/include/kvm/uip.h +++ b/tools/kvm/include/kvm/uip.h @@ -253,7 +253,7 @@ struct uip_tcp_socket { }; struct uip_tx_arg { - struct virtio_net_hdr *vnet; + void *vnet; struct uip_info *info; struct uip_eth *eth; int vnet_len; diff --git a/tools/kvm/net/uip/core.c b/tools/kvm/net/uip/core.c index e31efc2..789b814 100644 --- a/tools/kvm/net/uip/core.c +++ b/tools/kvm/net/uip/core.c @@ -8,7 +8,7 @@ int uip_tx(struct iovec *iov, u16 out, struct uip_info *info) { - struct virtio_net_hdr *vnet; + void *vnet; struct uip_tx_arg arg; int eth_len, vnet_len; struct uip_eth *eth; diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c index 15dbde3..7855cfc 100644 --- a/tools/kvm/virtio/net.c +++ b/tools/kvm/virtio/net.c @@ -8,6 +8,7 @@ #include "kvm/irq.h" #include "kvm/uip.h" #include "kvm/guest_compat.h" +#include "kvm/iovec.h" #include #include @@ -65,6 +66,13 @@ struct net_dev { static LIST_HEAD(ndevs); static int compat_id = -1; +#define MAX_PACKET_SIZE 65550 + +static bool has_virtio_feature(struct net_dev *ndev, u32 feature) +{ + return ndev->features & (1 << feature); +} + static void *virtio_net_rx_thread(void *p) { struct iovec iov[VIRTIO_NET_QUEUE_SIZE]; @@ -73,7 +81,7 @@ static void *virtio_net_rx_thread(void *p) struct net_dev *ndev = p; u16 out, in; u16 head; - int len; + size_t len, copied; u32 id; mutex_lock(&ndev->mutex); @@ -92,10 +100,31 @@ static void *virtio_net_rx_thread(void *p) mutex_unlock(&ndev->io_lock[id]); while (virt_queue__available(vq)) { + unsigned char buffer[MAX_PACKET_SIZE + sizeof(struct virtio_net_hdr_mrg_rxbuf)]; + struct iovec dummy_iov = { + .iov_base = buffer, + .iov_len = sizeof(buffer), + }; + struct virtio_net_hdr_mrg_rxbuf *hdr; + + len = ndev->ops->rx(&dummy_iov, 1, ndev); + copied = 0; head = virt_queue__get_iov(vq, iov, &out, &in, kvm); - len = ndev->ops->rx(iov, in, ndev); - virt_queue__set_used_elem(vq, head, len); - + hdr = (void *)iov[0].iov_base; + while (copied < len) { + size_t iovsize = min(len - copied, iov_size(iov, in)); + + memcpy_toiovecend(iov, buffer, copied, iovsize); + copied += iovsize; + if (has_virtio_feature(ndev, VIRTIO_NET_F_MRG_RXBUF)) + hdr->num_buffers++; + virt_queue__set_used_elem(vq, head, iovsize); + if (copied == len) + break; + while (!virt_queue__available(vq)) + sleep(0); + head = virt_queue__get_iov(vq, iov, &out, &in, kvm); + } /* We should interrupt guest right now, otherwise latency is huge. */ if (virtio_queue__should_signal(vq)) ndev->vdev.ops->signal_vq(kvm, &ndev->vdev, id); @@ -243,7 +272,7 @@ static bool virtio_net__tap_init(struct net_dev *ndev) goto fail; } - hdr_len = (ndev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) ? + hdr_len = has_virtio_feature(ndev, VIRTIO_NET_F_MRG_RXBUF) ? sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); if (ioctl(ndev->tap_fd, TUNSETVNETHDRSZ, &hdr_len) < 0) @@ -351,6 +380,7 @@ static u32 get_host_features(struct kvm *kvm, void *dev) | 1UL << VIRTIO_RING_F_EVENT_IDX | 1UL << VIRTIO_RING_F_INDIRECT_DESC | 1UL << VIRTIO_NET_F_CTRL_VQ + | 1UL << VIRTIO_NET_F_MRG_RXBUF | 1UL << (ndev->queue_pairs > 1 ? VIRTIO_NET_F_MQ : 0); } @@ -711,7 +741,7 @@ static void notify_status(struct kvm *kvm, void *dev, u8 status) if (!virtio_net__tap_init(ndev)) die_perror("You have requested a TAP device, but creation of one has failed because"); } else { - ndev->info.vnet_hdr_len = (ndev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) ? + ndev->info.vnet_hdr_len = has_virtio_feature(ndev, VIRTIO_NET_F_MRG_RXBUF) ? sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr); uip_init(&ndev->info);