qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@siemens.com>
To: qemu-devel@nongnu.org
Cc: Stefan Weil <sw@weilnetz.de>,
	Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>,
	Fabien Chouteau <chouteau@adacore.com>
Subject: [Qemu-devel] [PATCH 2/4] slirp: Fix queue walking in if_start
Date: Wed, 29 Feb 2012 20:15:45 +0100	[thread overview]
Message-ID: <3d42443a53940323f2f6a5d3a4a867a481c459ae.1330542945.git.jan.kiszka@siemens.com> (raw)
In-Reply-To: <cover.1330542945.git.jan.kiszka@siemens.com>
In-Reply-To: <cover.1330542945.git.jan.kiszka@siemens.com>

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 <chouteau@adacore.com>
CC: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com>
CC: Stefan Weil <sw@weilnetz.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 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;
-- 
1.7.3.4

  parent reply	other threads:[~2012-02-29 19:17 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-29 19:15 [Qemu-devel] [PATCH 0/4] slirp: Fix for requeuing crash, cleanups Jan Kiszka
2012-02-29 19:15 ` [Qemu-devel] [PATCH 1/4] slirp: Keep next_m always valid Jan Kiszka
2012-02-29 19:15 ` Jan Kiszka [this message]
2012-02-29 19:15 ` [Qemu-devel] [PATCH 3/4] slirp: Remove unneeded if_queued Jan Kiszka
2012-02-29 19:15 ` [Qemu-devel] [PATCH 4/4] slirp: Cleanup resources on instance removal Jan Kiszka
2012-02-29 19:19 ` [Qemu-devel] [PATCH 0/4] slirp: Fix for requeuing crash, cleanups Jan Kiszka
2012-02-29 21:00 ` Stefan Weil
2012-02-29 21:33   ` Jan Kiszka
2012-02-29 21:48     ` Stefan Weil
2012-02-29 21:52       ` Jan Kiszka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3d42443a53940323f2f6a5d3a4a867a481c459ae.1330542945.git.jan.kiszka@siemens.com \
    --to=jan.kiszka@siemens.com \
    --cc=chouteau@adacore.com \
    --cc=qemu-devel@nongnu.org \
    --cc=sw@weilnetz.de \
    --cc=wuzhy@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).