summaryrefslogtreecommitdiff
path: root/slirp/if.c
diff options
context:
space:
mode:
authorFabien Chouteau <chouteau@adacore.com>2011-08-01 18:18:37 +0200
committerJan Kiszka <jan.kiszka@siemens.com>2011-08-03 12:57:11 +0200
commit1ab74cea060d776b19857c3babc64d729bbdba5c (patch)
tree024f3b1df329cc1cbf5cd0069df0e585e5ffe957 /slirp/if.c
parent1a0ca1e1f6011a8623ec0653a1b35bbfc3f576c9 (diff)
downloadqemu-1ab74cea060d776b19857c3babc64d729bbdba5c.tar.gz
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.c28
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;
}