diff options
author | Fabien Chouteau <chouteau@adacore.com> | 2011-08-01 18:18:37 +0200 |
---|---|---|
committer | Jan Kiszka <jan.kiszka@siemens.com> | 2011-08-03 12:57:11 +0200 |
commit | 1ab74cea060d776b19857c3babc64d729bbdba5c (patch) | |
tree | 024f3b1df329cc1cbf5cd0069df0e585e5ffe957 /slirp/if.c | |
parent | 1a0ca1e1f6011a8623ec0653a1b35bbfc3f576c9 (diff) |
Delayed IP packets
In the current implementation, if Slirp tries to send an IP packet to a client
with an unknown hardware address, the packet is simply dropped and an ARP
request is sent (if_encap in slirp/slirp.c).
With this patch, Slirp will send the ARP request, re-queue the packet and try
to send it later. The packet is dropped after one second if the ARP reply is
not received.
Signed-off-by: Fabien Chouteau <chouteau@adacore.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Diffstat (limited to 'slirp/if.c')
-rw-r--r-- | slirp/if.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/slirp/if.c b/slirp/if.c index 0f04e13989..2d79e45bcd 100644 --- a/slirp/if.c +++ b/slirp/if.c @@ -6,6 +6,7 @@ */ #include <slirp.h> +#include "qemu-timer.h" #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm)) @@ -105,6 +106,9 @@ if_output(struct socket *so, struct mbuf *ifm) ifs_init(ifm); insque(ifm, ifq); + /* Expiration date = Now + 1 second */ + ifm->expiration_date = qemu_get_clock_ns(rt_clock) + 1000000000ULL; + diddit: slirp->if_queued++; @@ -153,6 +157,9 @@ diddit: void if_start(Slirp *slirp) { + int requeued = 0; + uint64_t now; + struct mbuf *ifm, *ifqt; DEBUG_CALL("if_start"); @@ -165,6 +172,8 @@ if_start(Slirp *slirp) if (!slirp_can_output(slirp->opaque)) return; + now = qemu_get_clock_ns(rt_clock); + /* * See which queue to get next packet from * If there's something in the fastq, select it immediately @@ -199,11 +208,22 @@ if_start(Slirp *slirp) ifm->ifq_so->so_nqueued = 0; } - /* Encapsulate the packet for sending */ - if_encap(slirp, (uint8_t *)ifm->m_data, ifm->m_len); - - m_free(ifm); + 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++; + } + } if (slirp->if_queued) goto again; + + slirp->if_queued = requeued; } |