From patchwork Thu Jun 30 08:40:49 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asias He X-Patchwork-Id: 932182 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p5U8iM5o029005 for ; Thu, 30 Jun 2011 08:44:22 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758693Ab1F3IoJ (ORCPT ); Thu, 30 Jun 2011 04:44:09 -0400 Received: from mail-iy0-f174.google.com ([209.85.210.174]:59621 "EHLO mail-iy0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757054Ab1F3Inv (ORCPT ); Thu, 30 Jun 2011 04:43:51 -0400 Received: by mail-iy0-f174.google.com with SMTP id 12so1722525iyb.19 for ; Thu, 30 Jun 2011 01:43:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=AnnkJyD57MrbhBGDhfdcxcrPs1lMm431Y/RBrTPs18s=; b=bDHInb7bm56iDZZzpBF9QhU5tS9OCkYGhM47d5nFeXdojA/XjlR2uhPmijHNMW3KNq nJs6J/hKkn0K5YlXhZd4+CXTp9+oRw/ysyh83uro59e/GnxHtLkaOr23rOkuc9vErDCP P393c2fxbOEZXQNiDObz29Mo+L/KPxoFaIMXA= Received: by 10.42.223.198 with SMTP id il6mr1864099icb.271.1309423431099; Thu, 30 Jun 2011 01:43:51 -0700 (PDT) Received: from localhost.localdomain ([219.224.169.130]) by mx.google.com with ESMTPS id d6sm1967338icx.1.2011.06.30.01.43.47 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 30 Jun 2011 01:43:50 -0700 (PDT) From: Asias He To: Pekka Enberg Cc: Cyrill Gorcunov , Ingo Molnar , Sasha Levin , Prasad Joshi , kvm@vger.kernel.org, Asias He Subject: [PATCH v2 01/31] kvm tools: Introduce ethernet frame buffer system for uip Date: Thu, 30 Jun 2011 16:40:49 +0800 Message-Id: <1309423279-3093-2-git-send-email-asias.hejun@gmail.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1309423279-3093-1-git-send-email-asias.hejun@gmail.com> References: <1309423279-3093-1-git-send-email-asias.hejun@gmail.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 30 Jun 2011 08:44:22 +0000 (UTC) - uip_buf_get_free() Get a free buffer from buffer pool, sleep if there is no free buffer. - uip_buf_get_used() Get a used buffer from buffer pool, sleep if there is no used buffer. - uip_buf_set_free() Set a buffer as free, so it can be reused by the buffer producer. - uip_buf_set_used() Set a buffer as used, uip rx code will inject the ethernet frame in this buffer into guest. - uip_buf_clone() Get a free buffer, and clone data into it. Signed-off-by: Asias He --- tools/kvm/Makefile | 1 + tools/kvm/include/kvm/uip.h | 69 ++++++++++++++++++++++++++ tools/kvm/uip/buf.c | 114 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 0 deletions(-) create mode 100644 tools/kvm/include/kvm/uip.h create mode 100644 tools/kvm/uip/buf.c diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index d368c22..91539de 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -45,6 +45,7 @@ OBJS += disk/qcow.o OBJS += disk/raw.o OBJS += ioeventfd.o OBJS += irq.o +OBJS += uip/buf.o OBJS += kvm-cmd.o OBJS += kvm-debug.o OBJS += kvm-help.o diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h new file mode 100644 index 0000000..32a5da3 --- /dev/null +++ b/tools/kvm/include/kvm/uip.h @@ -0,0 +1,69 @@ +#ifndef KVM__UIP_H +#define KVM__UIP_H + +#include "linux/types.h" +#include "kvm/mutex.h" + +#include +#include + +#define UIP_BUF_STATUS_FREE 0 +#define UIP_BUF_STATUS_INUSE 1 +#define UIP_BUF_STATUS_USED 2 + +struct uip_eth_addr { + u8 addr[6]; +}; + +struct uip_eth { + struct uip_eth_addr dst; + struct uip_eth_addr src; + u16 type; +} __attribute__((packed)); + +struct uip_info { + struct list_head udp_socket_head; + struct list_head tcp_socket_head; + pthread_mutex_t udp_socket_lock; + pthread_mutex_t tcp_socket_lock; + struct uip_eth_addr guest_mac; + struct uip_eth_addr host_mac; + pthread_cond_t buf_free_cond; + pthread_cond_t buf_used_cond; + struct list_head buf_head; + pthread_mutex_t buf_lock; + pthread_t udp_thread; + int udp_epollfd; + int buf_free_nr; + int buf_used_nr; + u32 host_ip; + u32 buf_nr; +}; + +struct uip_buf { + struct list_head list; + struct uip_info *info; + u32 payload; + int vnet_len; + int eth_len; + int status; + char *vnet; + char *eth; + int id; +}; + +struct uip_tx_arg { + struct virtio_net_hdr *vnet; + struct uip_info *info; + struct uip_eth *eth; + int vnet_len; + int eth_len; +}; + +struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf); +struct uip_buf *uip_buf_set_free(struct uip_info *info, struct uip_buf *buf); +struct uip_buf *uip_buf_get_used(struct uip_info *info); +struct uip_buf *uip_buf_get_free(struct uip_info *info); +struct uip_buf *uip_buf_clone(struct uip_tx_arg *arg); + +#endif /* KVM__UIP_H */ diff --git a/tools/kvm/uip/buf.c b/tools/kvm/uip/buf.c new file mode 100644 index 0000000..5e564a9 --- /dev/null +++ b/tools/kvm/uip/buf.c @@ -0,0 +1,114 @@ +#include "kvm/uip.h" + +#include +#include + +struct uip_buf *uip_buf_get_used(struct uip_info *info) +{ + struct uip_buf *buf; + bool found = false; + + mutex_lock(&info->buf_lock); + + while (!(info->buf_used_nr > 0)) + pthread_cond_wait(&info->buf_used_cond, &info->buf_lock); + + list_for_each_entry(buf, &info->buf_head, list) { + if (buf->status == UIP_BUF_STATUS_USED) { + /* + * Set status to INUSE immediately to prevent + * someone from using this buf until we free it + */ + buf->status = UIP_BUF_STATUS_INUSE; + info->buf_used_nr--; + found = true; + break; + } + } + + mutex_unlock(&info->buf_lock); + + return found ? buf : NULL; +} + +struct uip_buf *uip_buf_get_free(struct uip_info *info) +{ + struct uip_buf *buf; + bool found = false; + + mutex_lock(&info->buf_lock); + + while (!(info->buf_free_nr > 0)) + pthread_cond_wait(&info->buf_free_cond, &info->buf_lock); + + list_for_each_entry(buf, &info->buf_head, list) { + if (buf->status == UIP_BUF_STATUS_FREE) { + /* + * Set status to INUSE immediately to prevent + * someone from using this buf until we free it + */ + buf->status = UIP_BUF_STATUS_INUSE; + info->buf_free_nr--; + found = true; + break; + } + } + + mutex_unlock(&info->buf_lock); + + return found ? buf : NULL; +} + +struct uip_buf *uip_buf_set_used(struct uip_info *info, struct uip_buf *buf) +{ + mutex_lock(&info->buf_lock); + + buf->status = UIP_BUF_STATUS_USED; + info->buf_used_nr++; + pthread_cond_signal(&info->buf_used_cond); + + mutex_unlock(&info->buf_lock); + + return buf; +} + +struct uip_buf *uip_buf_set_free(struct uip_info *info, struct uip_buf *buf) +{ + mutex_lock(&info->buf_lock); + + buf->status = UIP_BUF_STATUS_FREE; + info->buf_free_nr++; + pthread_cond_signal(&info->buf_free_cond); + + mutex_unlock(&info->buf_lock); + + return buf; +} + +struct uip_buf *uip_buf_clone(struct uip_tx_arg *arg) +{ + struct uip_buf *buf; + struct uip_eth *eth2; + struct uip_info *info; + + info = arg->info; + + /* + * Get buffer from device to guest + */ + buf = uip_buf_get_free(info); + + /* + * Clone buffer + */ + memcpy(buf->vnet, arg->vnet, arg->vnet_len); + memcpy(buf->eth, arg->eth, arg->eth_len); + buf->vnet_len = arg->vnet_len; + buf->eth_len = arg->eth_len; + + eth2 = (struct uip_eth *)buf->eth; + eth2->src = info->host_mac; + eth2->dst = arg->eth->src; + + return buf; +}