aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2012-02-17 16:26:38 +0100
committerJan Kiszka <jan.kiszka@siemens.com>2012-02-27 14:54:49 +0100
commit51779453692529fdabd07f6a0aeca596ab79d5ce (patch)
tree8636a0ecadb777f73fe96cf10850cbea1ebe6b42
parent8b5bd96b65fc56bbb60dc6de6184abaab23e0349 (diff)
downloadslirp-51779453692529fdabd07f6a0aeca596ab79d5ce.zip
slirp-51779453692529fdabd07f6a0aeca596ab79d5ce.tar.gz
slirp-51779453692529fdabd07f6a0aeca596ab79d5ce.tar.bz2
slirp: Fix requeuing of batchq packets in if_start
In case we requeued a packet that was the head of a longer session queue, we failed to restore this ordering. Also, we did not properly deal with changes to Slirp::next_m. Instead of a cumbersome roll back, this fix simply avoids any changes until we know if the packet was actually sent. Both fixes crashes due to inconsistent queues and simplifies the logic. Thanks to Zhi Yong Wu who found the reason for these crashes. CC: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com> CC: Fabien Chouteau <chouteau@adacore.com> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
-rw-r--r--if.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/if.c b/if.c
index c72a264..b0c11e9 100644
--- a/if.c
+++ b/if.c
@@ -149,6 +149,7 @@ 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;
DEBUG_CALL("if_start");
@@ -174,13 +175,26 @@ again:
else
ifm = slirp->if_batchq.ifq_next;
+ from_batchq = true;
+ }
+
+ slirp->if_queued--;
+
+ /* Try to send packet unless it already expired */
+ if (ifm->expiration_date >= now && !if_encap(slirp, ifm)) {
+ /* Packet is delayed due to pending ARP resolution */
+ requeued++;
+ goto out;
+ }
+
+ if (from_batchq) {
/* Set which packet to send on next iteration */
slirp->next_m = ifm->ifq_next;
}
+
/* Remove it from the queue */
ifqt = ifm->ifq_prev;
remque(ifm);
- slirp->if_queued--;
/* If there are more packets for this session, re-queue them */
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
@@ -195,20 +209,9 @@ again:
ifm->ifq_so->so_nqueued = 0;
}
- if (ifm->expiration_date < now) {
- /* Expired */
- m_free(ifm);
- } else {
- /* Encapsulate the packet for sending */
- if (if_encap(slirp, ifm)) {
- m_free(ifm);
- } else {
- /* re-queue */
- insque(ifm, ifqt);
- requeued++;
- }
- }
+ m_free(ifm);
+out:
if (slirp->if_queued)
goto again;