diff --git a/main-loop.c b/main-loop.c index 1c38ea2b9397550b460acd46955f42bae5989d37..c3c9c28fbab786e0c50a5d1882d155680f0d46b9 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 ceabff81b2cc85f4453a262ddb0a6285bd2aac33..5bdcbd50f7ec4acc41b4017d8f538d2f3127a4b2 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 5c3dabba9342ebd8eea1bf9d144d864c4d340416..bad8dad02e97e5350bf966dfa627ccd862d3edd2 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); @@ -49,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) @@ -59,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; } @@ -115,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; } @@ -259,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(1000, *timeout); + Slirp *slirp; + uint32_t t; + + if (*timeout <= TIMEOUT_FAST) { + return; + } + + t = MIN(1000, *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; @@ -278,14 +300,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 +320,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 +403,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 +444,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 */ } } @@ -436,6 +458,7 @@ void slirp_pollfds_fill(GArray *pollfds) } } } + slirp_update_timeout(timeout); } void slirp_pollfds_poll(GArray *pollfds, int select_error) @@ -454,14 +477,16 @@ 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) >= TIMEOUT_FAST)) { 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) >= TIMEOUT_SLOW)) { ip_slowtimo(slirp); tcp_slowtimo(slirp); - last_slowtimo = curtime; + slirp->last_slowtimo = curtime; } /* diff --git a/slirp/slirp.h b/slirp/slirp.h index fe0e65d0eee0bd1442caf2a8df3a67a8d6fd28b3..e4a1bd4abb19e9e24759edd633d1db119a8313b3 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; diff --git a/stubs/slirp.c b/stubs/slirp.c index f1fc833f7aa9e981e2b9913e87bff2749af5f8a9..bd0ac7f27de4374c447f983cea8ebd2209e20fff 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) { }