From patchwork Thu Aug 23 12:47:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asias He X-Patchwork-Id: 1366931 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 793D53FC66 for ; Thu, 23 Aug 2012 12:48:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756050Ab2HWMsT (ORCPT ); Thu, 23 Aug 2012 08:48:19 -0400 Received: from mail-yx0-f174.google.com ([209.85.213.174]:63465 "EHLO mail-yx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752031Ab2HWMsS (ORCPT ); Thu, 23 Aug 2012 08:48:18 -0400 Received: by yenl14 with SMTP id l14so163656yen.19 for ; Thu, 23 Aug 2012 05:48:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=Cz4OgzdtPhpiKfyePYdnzLKr2gPP0sb5OUOFvceYRWg=; b=nuZaZvxs+AOHrmgZry9x6d18/qTXhNhzYazuhS41mAFTEfjp8UGqbDcpBVb6q1HspS zwRqb02Rwyk20QCaWHGmBQF1genMS51ZfhsBDDug8vqv5BRu4SQi6zDqvkF73/VyxQqd Cnm2T7mWalDUOa0BuvWXjJ0UvRpsoFws8T0cxZKeHG7HAaK81NAgeY+EGnEdA9Bbn8e/ UeNQEtepNC5iEqjmZ7ARv4Ad7WmTZ6E19ZkyxHRAE+QSxsqAb6P/xZI4+HZ8oO+HMSH3 L2s4Pos4cJ6onMAHqyUW4tHVN0zEEq6DaRWu/WWcbNvBh9Y2m6L/E3w+42cycntnViu5 kb8Q== Received: by 10.236.191.69 with SMTP id f45mr1137779yhn.8.1345726097505; Thu, 23 Aug 2012 05:48:17 -0700 (PDT) Received: from hj.localdomain.com ([58.194.229.103]) by mx.google.com with ESMTPS id n5sm6657623ang.18.2012.08.23.05.48.15 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 23 Aug 2012 05:48:17 -0700 (PDT) From: Asias He To: Pekka Enberg Cc: Sasha Levin , Ingo Molnar , Cyrill Gorcunov , kvm@vger.kernel.org Subject: [PATCH V2 2/2] kvm tools: Respect guest tcp window size Date: Thu, 23 Aug 2012 20:47:51 +0800 Message-Id: <1345726071-3517-2-git-send-email-asias.hejun@gmail.com> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1345726071-3517-1-git-send-email-asias.hejun@gmail.com> References: <1345726071-3517-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 Respect guest tcp window size and stop sending tcp segments to guest if guest's receive window is closed. This fixes the TCP hang I'm seeing where guest and host are transferring big chuck of data. This problem was not triggered when guest and external host communicates, probably because guest to external host communication walks through real network and is much slower than guest and host communication. Thus, guest's receive window has little chance to be closed. v2: use pthread_cond_wait to wait Signed-off-by: Asias He --- tools/kvm/include/kvm/uip.h | 2 ++ tools/kvm/net/uip/tcp.c | 36 ++++++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h index 4497f6a..9af0110 100644 --- a/tools/kvm/include/kvm/uip.h +++ b/tools/kvm/include/kvm/uip.h @@ -231,10 +231,12 @@ struct uip_tcp_socket { struct sockaddr_in addr; struct list_head list; struct uip_info *info; + pthread_cond_t cond; pthread_mutex_t *lock; pthread_t thread; u32 dport, sport; u32 guest_acked; + u16 window_size; /* * Initial Sequence Number */ diff --git a/tools/kvm/net/uip/tcp.c b/tools/kvm/net/uip/tcp.c index 68a1d6e..711a716 100644 --- a/tools/kvm/net/uip/tcp.c +++ b/tools/kvm/net/uip/tcp.c @@ -70,6 +70,8 @@ static struct uip_tcp_socket *uip_tcp_socket_alloc(struct uip_tx_arg *arg, u32 s sk->addr.sin_port = dport; sk->addr.sin_addr.s_addr = dip; + pthread_cond_init(&sk->cond, NULL); + if (ntohl(dip) == arg->info->host_ip) sk->addr.sin_addr.s_addr = inet_addr("127.0.0.1"); @@ -171,25 +173,41 @@ static int uip_tcp_payload_send(struct uip_tcp_socket *sk, u8 flag, u16 payload_ static void *uip_tcp_socket_thread(void *p) { struct uip_tcp_socket *sk; - u8 *payload; - int ret; + int len, left, ret; + u8 *payload, *pos; sk = p; payload = malloc(UIP_MAX_TCP_PAYLOAD); - sk->payload = payload; - if (!sk->payload) + if (!payload) goto out; while (1) { + pos = payload; ret = read(sk->fd, payload, UIP_MAX_TCP_PAYLOAD); if (ret <= 0 || ret > UIP_MAX_TCP_PAYLOAD) goto out; - uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, ret); + left = ret; + + while (left > 0) { + mutex_lock(sk->lock); + while ((len = sk->guest_acked + sk->window_size - sk->seq_server) <= 0) + pthread_cond_wait(&sk->cond, sk->lock); + mutex_unlock(sk->lock); + sk->payload = pos; + if (len > left) + len = left; + if (len > UIP_MAX_TCP_PAYLOAD) + len = UIP_MAX_TCP_PAYLOAD; + left -= len; + pos += len; + + uip_tcp_payload_send(sk, UIP_TCP_FLAG_ACK, len); + } } out: @@ -203,7 +221,7 @@ out: sk->read_done = 1; - free(sk->payload); + free(payload); pthread_exit(NULL); return NULL; @@ -254,6 +272,8 @@ int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg) if (!sk) return -1; + sk->window_size = ntohs(tcp->win); + /* * Setup ISN number */ @@ -280,7 +300,11 @@ int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg) if (!sk) return -1; + mutex_lock(sk->lock); + sk->window_size = ntohs(tcp->win); sk->guest_acked = ntohl(tcp->ack); + pthread_cond_signal(&sk->cond); + mutex_unlock(sk->lock); if (uip_tcp_is_fin(tcp)) { if (sk->write_done)