From patchwork Thu Aug 23 01:26: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: 1364091 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 184FBDF215 for ; Thu, 23 Aug 2012 01:28:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751591Ab2HWB2L (ORCPT ); Wed, 22 Aug 2012 21:28:11 -0400 Received: from mail-yw0-f46.google.com ([209.85.213.46]:51218 "EHLO mail-yw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751452Ab2HWB2J (ORCPT ); Wed, 22 Aug 2012 21:28:09 -0400 Received: by yhmm54 with SMTP id m54so87112yhm.19 for ; Wed, 22 Aug 2012 18:28:09 -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; bh=jD5ivy3jU8Yt/LRohED0waVOJACDdEidZYdStkzR3sc=; b=GE3YcX+Hitco+zbOcw/2uGMH6xSbBRKqW0evop5EnlhpaR9ATrlgg8Afwz+ne2tYHg Ei/fnhicNGgOEQjzxk6mDycCtqX+4R/fBdTozKAZZ/Qj7A0CzJoEH46J8NkY7kebrZWC MayIgOPZd41qnemLj8RtgIfCk1q9NKrYsstlaP5WPDDJ/pqx1S2ASU04z1VA+d/uUB4M axjDo7zvMJ0/jUhWrb+YBOU6jK6opCesdLz7SXPZeEI+pLeGlVx/q4QlinZTLE2hM1kM 9lo7P7cuWVfscJZRZ5K7cb0HAgJDinb6u6cRVlvYlcC+x+9WPkk8AzMkZnX0BNdbEKFP e99w== Received: by 10.236.200.132 with SMTP id z4mr30679541yhn.93.1345685288942; Wed, 22 Aug 2012 18:28:08 -0700 (PDT) Received: from hj.localdomain.com ([58.194.229.103]) by mx.google.com with ESMTPS id p36sm10856450yhe.20.2012.08.22.18.28.06 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 22 Aug 2012 18:28:08 -0700 (PDT) From: Asias He To: Pekka Enberg Cc: Sasha Levin , Ingo Molnar , Cyrill Gorcunov , kvm@vger.kernel.org Subject: [PATCH 1/2] kvm tools: Respect guest tcp window size Date: Thu, 23 Aug 2012 09:26:51 +0800 Message-Id: <1345685212-8081-1-git-send-email-asias.hejun@gmail.com> X-Mailer: git-send-email 1.7.11.4 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. Signed-off-by: Asias He --- tools/kvm/include/kvm/uip.h | 1 + tools/kvm/net/uip/tcp.c | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h index 4497f6a..191029b 100644 --- a/tools/kvm/include/kvm/uip.h +++ b/tools/kvm/include/kvm/uip.h @@ -235,6 +235,7 @@ struct uip_tcp_socket { 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 586a45c..cf46bac 100644 --- a/tools/kvm/net/uip/tcp.c +++ b/tools/kvm/net/uip/tcp.c @@ -167,25 +167,38 @@ 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; + u8 *payload, *pos; + int len, left, ret; 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) { + while ((len = sk->guest_acked + sk->window_size - sk->seq_server) <= 0) + usleep(100); + 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: @@ -199,7 +212,7 @@ out: sk->read_done = 1; - free(sk->payload); + free(payload); pthread_exit(NULL); return NULL; @@ -250,6 +263,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 */ @@ -276,6 +291,7 @@ int uip_tx_do_ipv4_tcp(struct uip_tx_arg *arg) if (!sk) return -1; + sk->window_size = ntohs(tcp->win); sk->guest_acked = ntohl(tcp->ack); if (uip_tcp_is_fin(tcp)) {