“952a0bf831e83eaf05082edb76006c970a2a6f61”上不存在“release/0.10.0/doc/genindex.html”
提交 b248ede2 编写于 作者: J Jan Kiszka

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: NJan Kiszka <jan.kiszka@siemens.com>
上级 79e7e937
...@@ -154,6 +154,7 @@ if_start(Slirp *slirp) ...@@ -154,6 +154,7 @@ if_start(Slirp *slirp)
{ {
uint64_t now = qemu_get_clock_ns(rt_clock); uint64_t now = qemu_get_clock_ns(rt_clock);
int requeued = 0; int requeued = 0;
bool from_batchq = false;
struct mbuf *ifm, *ifqt; struct mbuf *ifm, *ifqt;
DEBUG_CALL("if_start"); DEBUG_CALL("if_start");
...@@ -179,13 +180,26 @@ if_start(Slirp *slirp) ...@@ -179,13 +180,26 @@ if_start(Slirp *slirp)
else else
ifm = slirp->if_batchq.ifq_next; ifm = slirp->if_batchq.ifq_next;
/* Set which packet to send on next iteration */ from_batchq = true;
slirp->next_m = ifm->ifq_next;
} }
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 */ /* Remove it from the queue */
ifqt = ifm->ifq_prev; ifqt = ifm->ifq_prev;
remque(ifm); remque(ifm);
slirp->if_queued--;
/* If there are more packets for this session, re-queue them */ /* If there are more packets for this session, re-queue them */
if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) { if (ifm->ifs_next != /* ifm->ifs_prev != */ ifm) {
...@@ -200,20 +214,9 @@ if_start(Slirp *slirp) ...@@ -200,20 +214,9 @@ if_start(Slirp *slirp)
ifm->ifq_so->so_nqueued = 0; ifm->ifq_so->so_nqueued = 0;
} }
if (ifm->expiration_date < now) { m_free(ifm);
/* 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++;
}
}
out:
if (slirp->if_queued) if (slirp->if_queued)
goto again; goto again;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册