From fe0ff43c9d8ccf45effdade8d40e44aed421187f Mon Sep 17 00:00:00 2001 From: Liu Ping Fan Date: Sun, 25 Aug 2013 10:01:19 +0800 Subject: [PATCH 1/4] slirp: make timeout local Each slirp has its own time to caculate timeout. Signed-off-by: Liu Ping Fan Signed-off-by: Jan Kiszka --- slirp/slirp.c | 22 ++++++++++------------ slirp/slirp.h | 3 +++ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/slirp/slirp.c b/slirp/slirp.c index 5c3dabba93..b3ef4fe08b 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -40,8 +40,6 @@ static const uint8_t special_ethaddr[ETH_ALEN] = { static const uint8_t zero_ethaddr[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; u_int curtime; -static u_int time_fasttimo, last_slowtimo; -static int do_slowtimo; static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances = QTAILQ_HEAD_INITIALIZER(slirp_instances); @@ -278,14 +276,13 @@ void slirp_pollfds_fill(GArray *pollfds) /* * First, TCP sockets */ - do_slowtimo = 0; QTAILQ_FOREACH(slirp, &slirp_instances, entry) { /* * *_slowtimo needs calling if there are IP fragments * in the fragment queue, or there are TCP connections active */ - do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) || + slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) || (&slirp->ipq.ip_link != slirp->ipq.ip_link.next)); for (so = slirp->tcb.so_next; so != &slirp->tcb; @@ -299,8 +296,9 @@ void slirp_pollfds_fill(GArray *pollfds) /* * See if we need a tcp_fasttimo */ - if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) { - time_fasttimo = curtime; /* Flag when we want a fasttimo */ + if (slirp->time_fasttimo == 0 && + so->so_tcpcb->t_flags & TF_DELACK) { + slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */ } /* @@ -381,7 +379,7 @@ void slirp_pollfds_fill(GArray *pollfds) udp_detach(so); continue; } else { - do_slowtimo = 1; /* Let socket expire */ + slirp->do_slowtimo = true; /* Let socket expire */ } } @@ -422,7 +420,7 @@ void slirp_pollfds_fill(GArray *pollfds) icmp_detach(so); continue; } else { - do_slowtimo = 1; /* Let socket expire */ + slirp->do_slowtimo = true; /* Let socket expire */ } } @@ -454,14 +452,14 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) /* * See if anything has timed out */ - if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { + if (slirp->time_fasttimo && ((curtime - slirp->time_fasttimo) >= 2)) { tcp_fasttimo(slirp); - time_fasttimo = 0; + slirp->time_fasttimo = 0; } - if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) { + if (slirp->do_slowtimo && ((curtime - slirp->last_slowtimo) >= 499)) { ip_slowtimo(slirp); tcp_slowtimo(slirp); - last_slowtimo = curtime; + slirp->last_slowtimo = curtime; } /* diff --git a/slirp/slirp.h b/slirp/slirp.h index fe0e65d0ee..e4a1bd4abb 100644 --- a/slirp/slirp.h +++ b/slirp/slirp.h @@ -203,6 +203,9 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr, struct Slirp { QTAILQ_ENTRY(Slirp) entry; + u_int time_fasttimo; + u_int last_slowtimo; + bool do_slowtimo; /* virtual network configuration */ struct in_addr vnetwork_addr; From 9b0ca6cc64d3542be35f1ca6174de2ab6af30ed0 Mon Sep 17 00:00:00 2001 From: Liu Ping Fan Date: Sun, 25 Aug 2013 10:01:20 +0800 Subject: [PATCH 2/4] slirp: define timeout as macro Signed-off-by: Liu Ping Fan Signed-off-by: Jan Kiszka --- slirp/slirp.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/slirp/slirp.c b/slirp/slirp.c index b3ef4fe08b..23e60a0923 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -47,6 +47,11 @@ static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances = static struct in_addr dns_addr; static u_int dns_addr_time; +#define TIMEOUT_FAST 2 /* milliseconds */ +#define TIMEOUT_SLOW 499 /* milliseconds */ +/* for the aging of certain requests like DNS */ +#define TIMEOUT_DEFAULT 1000 /* milliseconds */ + #ifdef _WIN32 int get_dns_addr(struct in_addr *pdns_addr) @@ -57,7 +62,7 @@ int get_dns_addr(struct in_addr *pdns_addr) IP_ADDR_STRING *pIPAddr; struct in_addr tmp_addr; - if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < 1000) { + if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < TIMEOUT_DEFAULT) { *pdns_addr = dns_addr; return 0; } @@ -113,7 +118,7 @@ int get_dns_addr(struct in_addr *pdns_addr) if (dns_addr.s_addr != 0) { struct stat old_stat; - if ((curtime - dns_addr_time) < 1000) { + if ((curtime - dns_addr_time) < TIMEOUT_DEFAULT) { *pdns_addr = dns_addr; return 0; } @@ -260,7 +265,7 @@ void slirp_cleanup(Slirp *slirp) void slirp_update_timeout(uint32_t *timeout) { if (!QTAILQ_EMPTY(&slirp_instances)) { - *timeout = MIN(1000, *timeout); + *timeout = MIN(TIMEOUT_DEFAULT, *timeout); } } @@ -452,11 +457,13 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error) /* * See if anything has timed out */ - if (slirp->time_fasttimo && ((curtime - slirp->time_fasttimo) >= 2)) { + if (slirp->time_fasttimo && + ((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) { tcp_fasttimo(slirp); slirp->time_fasttimo = 0; } - if (slirp->do_slowtimo && ((curtime - slirp->last_slowtimo) >= 499)) { + if (slirp->do_slowtimo && + ((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) { ip_slowtimo(slirp); tcp_slowtimo(slirp); slirp->last_slowtimo = curtime; From a42e9c41888bc6a5446ef6bd95745c9fd023f107 Mon Sep 17 00:00:00 2001 From: Liu Ping Fan Date: Sun, 25 Aug 2013 10:01:21 +0800 Subject: [PATCH 3/4] slirp: set mainloop timeout with more precise value If slirp needs to emulate tcp timeout, then the timeout value for mainloop should be more precise, which is determined by slirp's fasttimo or slowtimo. Achieve this by swap the logic sequence of slirp_pollfds_fill and slirp_update_timeout. Signed-off-by: Liu Ping Fan Signed-off-by: Jan Kiszka --- main-loop.c | 3 +-- slirp/libslirp.h | 3 +-- slirp/slirp.c | 28 ++++++++++++++++++++++++---- stubs/slirp.c | 6 +----- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/main-loop.c b/main-loop.c index 1c38ea2b93..c3c9c28fba 100644 --- a/main-loop.c +++ b/main-loop.c @@ -466,8 +466,7 @@ int main_loop_wait(int nonblocking) g_array_set_size(gpollfds, 0); /* reset for new iteration */ /* XXX: separate device handlers from system ones */ #ifdef CONFIG_SLIRP - slirp_update_timeout(&timeout); - slirp_pollfds_fill(gpollfds); + slirp_pollfds_fill(gpollfds, &timeout); #endif qemu_iohandler_fill(gpollfds); diff --git a/slirp/libslirp.h b/slirp/libslirp.h index ceabff81b2..5bdcbd50f7 100644 --- a/slirp/libslirp.h +++ b/slirp/libslirp.h @@ -16,8 +16,7 @@ Slirp *slirp_init(int restricted, struct in_addr vnetwork, void *opaque); void slirp_cleanup(Slirp *slirp); -void slirp_update_timeout(uint32_t *timeout); -void slirp_pollfds_fill(GArray *pollfds); +void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout); void slirp_pollfds_poll(GArray *pollfds, int select_error); diff --git a/slirp/slirp.c b/slirp/slirp.c index 23e60a0923..fe16367db8 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -262,14 +262,33 @@ void slirp_cleanup(Slirp *slirp) #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED) -void slirp_update_timeout(uint32_t *timeout) +static void slirp_update_timeout(uint32_t *timeout) { - if (!QTAILQ_EMPTY(&slirp_instances)) { - *timeout = MIN(TIMEOUT_DEFAULT, *timeout); + Slirp *slirp; + uint32_t t; + + if (*timeout <= TIMEOUT_FAST) { + return; } + *timeout = MIN(1000, *timeout); + t = *timeout; + + /* If we have tcp timeout with slirp, then we will fill @timeout with + * more precise value. + */ + QTAILQ_FOREACH(slirp, &slirp_instances, entry) { + if (slirp->time_fasttimo) { + *timeout = TIMEOUT_FAST; + return; + } + if (slirp->do_slowtimo) { + t = MIN(TIMEOUT_SLOW, t); + } + } + *timeout = t; } -void slirp_pollfds_fill(GArray *pollfds) +void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout) { Slirp *slirp; struct socket *so, *so_next; @@ -439,6 +458,7 @@ void slirp_pollfds_fill(GArray *pollfds) } } } + slirp_update_timeout(timeout); } void slirp_pollfds_poll(GArray *pollfds, int select_error) diff --git a/stubs/slirp.c b/stubs/slirp.c index f1fc833f7a..bd0ac7f27d 100644 --- a/stubs/slirp.c +++ b/stubs/slirp.c @@ -1,11 +1,7 @@ #include "qemu-common.h" #include "slirp/slirp.h" -void slirp_update_timeout(uint32_t *timeout) -{ -} - -void slirp_pollfds_fill(GArray *pollfds) +void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout) { } From 426e3e6ce1abdb0d85faefbfac3cf4dcc7f224a3 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Wed, 28 Aug 2013 19:12:15 +0200 Subject: [PATCH 4/4] slirp: clean up slirp_update_timeout No need to write out the timeout early, keep it local until we are done. Signed-off-by: Jan Kiszka --- slirp/slirp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slirp/slirp.c b/slirp/slirp.c index fe16367db8..bad8dad02e 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -270,8 +270,8 @@ static void slirp_update_timeout(uint32_t *timeout) if (*timeout <= TIMEOUT_FAST) { return; } - *timeout = MIN(1000, *timeout); - t = *timeout; + + t = MIN(1000, *timeout); /* If we have tcp timeout with slirp, then we will fill @timeout with * more precise value.