diff options
Diffstat (limited to 'slirp/if.c')
-rw-r--r-- | slirp/if.c | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/slirp/if.c b/slirp/if.c index f7aebe9557..f6e848a31a 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -158,8 +158,8 @@ 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, next_from_batchq; + struct mbuf *ifm, *ifm_next, *ifqt; DEBUG_CALL("if_start"); @@ -168,23 +168,36 @@ void if_start(Slirp *slirp) } slirp->if_start_busy = true; - while (slirp->if_queued) { + if (slirp->if_fastq.ifq_next != &slirp->if_fastq) { + ifm_next = slirp->if_fastq.ifq_next; + next_from_batchq = false; + } else if (slirp->next_m != &slirp->if_batchq) { + /* Nothing on fastq, pick up from batchq via next_m */ + ifm_next = slirp->next_m; + next_from_batchq = true; + } else { + ifm_next = NULL; + } + + while (ifm_next) { /* check if we can really output */ if (!slirp_can_output(slirp->opaque)) { slirp->if_start_busy = false; 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 = next_from_batchq; + + ifm_next = ifm->ifq_next; + if (ifm_next == &slirp->if_fastq) { + /* No more packets in fastq, switch to batchq */ + ifm_next = slirp->next_m; + next_from_batchq = true; + } + if (ifm_next == &slirp->if_batchq) { + /* end of batchq */ + ifm_next = NULL; } slirp->if_queued--; @@ -196,7 +209,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; } @@ -207,13 +220,19 @@ void if_start(Slirp *slirp) /* If there are more packets for this session, re-queue them */ if (ifm->ifs_next != ifm) { - insque(ifm->ifs_next, ifqt); + struct mbuf *next = ifm->ifs_next; + + insque(next, ifqt); ifs_remque(ifm); - /* Set next_m if the session packet is now the only one on - * batchq */ - if (ifqt == &slirp->if_batchq && - slirp->next_m == &slirp->if_batchq) { - slirp->next_m = ifm->ifs_next; + + if (!from_batchq) { + /* Next packet in fastq is from the same session */ + ifm_next = next; + next_from_batchq = false; + } else if (slirp->next_m == &slirp->if_batchq) { + /* Set next_m and ifm_next if the session packet is now the + * only one on batchq */ + slirp->next_m = ifm_next = next; } } @@ -224,7 +243,6 @@ void if_start(Slirp *slirp) } m_free(ifm); - } slirp->if_queued = requeued; |