From patchwork Wed Feb 29 19:15:45 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 143811 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8BF15B6EE7 for ; Thu, 1 Mar 2012 06:17:38 +1100 (EST) Received: from localhost ([::1]:39546 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S2p1s-0000Ta-CV for incoming@patchwork.ozlabs.org; Wed, 29 Feb 2012 14:17:36 -0500 Received: from eggs.gnu.org ([208.118.235.92]:36992) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S2p1L-0008Gr-Ry for qemu-devel@nongnu.org; Wed, 29 Feb 2012 14:17:26 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S2p1G-00012F-HD for qemu-devel@nongnu.org; Wed, 29 Feb 2012 14:17:03 -0500 Received: from goliath.siemens.de ([192.35.17.28]:22287) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S2p1F-000117-M8 for qemu-devel@nongnu.org; Wed, 29 Feb 2012 14:16:58 -0500 Received: from mail1.siemens.de (localhost [127.0.0.1]) by goliath.siemens.de (8.13.6/8.13.6) with ESMTP id q1TJFnXV010925; Wed, 29 Feb 2012 20:15:49 +0100 Received: from mchn199C.mchp.siemens.de ([139.25.109.49]) by mail1.siemens.de (8.13.6/8.13.6) with ESMTP id q1TJFlH1003174; Wed, 29 Feb 2012 20:15:48 +0100 From: Jan Kiszka To: qemu-devel@nongnu.org Date: Wed, 29 Feb 2012 20:15:45 +0100 Message-Id: <3d42443a53940323f2f6a5d3a4a867a481c459ae.1330542945.git.jan.kiszka@siemens.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 192.35.17.28 Cc: Stefan Weil , Zhi Yong Wu , Fabien Chouteau Subject: [Qemu-devel] [PATCH 2/4] slirp: Fix queue walking in if_start X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Another attempt to get this right: We need to carefully walk both the fastq and the batchq in if_start while trying to send packets to possibly not yet resolved hosts on the virtual network. So far we just requeued a delayed packet where it was and then started walking the queues from the top again - that couldn't work. Now we pre- calculate the next packet in the queue so that the current one can safely be removed if it was sent successfully. We also need to take into account that the next packet can be from the same session if the current one was sent or from another if it wasn't sent. CC: Fabien Chouteau CC: Zhi Yong Wu CC: Stefan Weil Signed-off-by: Jan Kiszka --- slirp/if.c | 50 ++++++++++++++++++++++++++++++++++---------------- 1 files changed, 34 insertions(+), 16 deletions(-) diff --git a/slirp/if.c b/slirp/if.c index 166852a..78a9b78 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -158,26 +158,41 @@ void if_start(Slirp *slirp) { uint64_t now = qemu_get_clock_ns(rt_clock); int requeued = 0; - bool from_batchq = false; - struct mbuf *ifm, *ifqt; + bool from_batchq, from_batchq_next; + struct mbuf *ifm, *ifm_next, *ifqt; DEBUG_CALL("if_start"); - while (slirp->if_queued) { + if (slirp->if_fastq.ifq_next != &slirp->if_fastq) { + ifm_next = slirp->if_fastq.ifq_next; + from_batchq_next = false; + } else if (slirp->next_m != &slirp->if_batchq) { + /* Nothing on fastq, pick up from batchq via next_m */ + ifm_next = slirp->next_m; + from_batchq_next = true; + } else { + ifm_next = NULL; + } + + while (ifm_next) { /* check if we can really output */ - if (!slirp_can_output(slirp->opaque)) + if (!slirp_can_output(slirp->opaque)) { return; + } - /* - * See which queue to get next packet from - * If there's something in the fastq, select it immediately - */ - if (slirp->if_fastq.ifq_next != &slirp->if_fastq) { - ifm = slirp->if_fastq.ifq_next; - } else { - /* Nothing on fastq, pick up from batchq via next_m */ - ifm = slirp->next_m; - from_batchq = true; + ifm = ifm_next; + from_batchq = from_batchq_next; + + ifm_next = ifm->ifq_next; + if (!from_batchq) { + if (ifm_next == &slirp->if_fastq) { + /* No more packets in fastq, switch to batchq */ + ifm_next = slirp->next_m; + from_batchq_next = true; + } + } else if (ifm_next == &slirp->if_batchq) { + /* end of batchq */ + ifm_next = NULL; } slirp->if_queued--; @@ -189,7 +204,7 @@ void if_start(Slirp *slirp) continue; } - if (from_batchq) { + if (ifm == slirp->next_m) { /* Set which packet to send on next iteration */ slirp->next_m = ifm->ifq_next; } @@ -202,6 +217,10 @@ void if_start(Slirp *slirp) if (ifm->ifs_next != ifm) { insque(ifm->ifs_next, ifqt); ifs_remque(ifm); + /* Also update ifm_next to point to this next session packet, + * same for from_batchq_next */ + ifm_next = ifm->ifs_next; + from_batchq_next = from_batchq; } /* Update so_queued */ @@ -211,7 +230,6 @@ void if_start(Slirp *slirp) } m_free(ifm); - } slirp->if_queued = requeued;