libs/libc/netdb: Optimize the timeout calculation logic:
1. Adopt an exponential backoff strategy () to dynamically adjust the timeout duration, which is suitable for retry scenarios. 2. Optimize the default configuration to set the initial timeout to 5 seconds. 3. Support dynamic modification of the maximum timeout limit to adapt to different scenarios. Reference: RFC 1536 (section on retransmission implementation recommendations) Signed-off-by: nuttxs <zhaoqing.zhang@sony.com>
This commit is contained in:
parent
c506c25f19
commit
7b3913da60
4 changed files with 45 additions and 12 deletions
|
|
@ -140,7 +140,7 @@ config NETDB_DNSCLIENT_MAXRESPONSE
|
|||
|
||||
config NETDB_DNSCLIENT_RECV_TIMEOUT
|
||||
int "DNS receive timeout"
|
||||
default 30
|
||||
default 5
|
||||
---help---
|
||||
This is the timeout value when DNS receives response after
|
||||
dns_send_query, unit: seconds
|
||||
|
|
@ -152,6 +152,15 @@ config NETDB_DNSCLIENT_SEND_TIMEOUT
|
|||
This is the timeout value when DNS send request on dns_send_query,
|
||||
unit: seconds
|
||||
|
||||
config NETDB_DNSCLIENT_MAX_TIMEOUT
|
||||
int "DNS maximum timeout"
|
||||
default 30
|
||||
---help---
|
||||
Maximum timeout value in seconds when using exponential backoff
|
||||
for DNS retries. The timeout grows exponentially with each retry
|
||||
(base_timeout * 2^retry_count) but is capped at this maximum value.
|
||||
Set to 0 to disable the cap.
|
||||
|
||||
config NETDB_DNSCLIENT_RETRIES
|
||||
int "Number of retries for DNS request"
|
||||
default 3
|
||||
|
|
|
|||
|
|
@ -162,7 +162,9 @@ void dns_restorelock(unsigned int count);
|
|||
* server. The name server was previously selected via dns_server().
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
* family - Address family (AF_INET or AF_INET6)
|
||||
* stream - Whether to use stream socket
|
||||
* retry_count - Current retry attempt (0 for first attempt)
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, the bound, non-negative socket descriptor is returned. A
|
||||
|
|
@ -170,7 +172,7 @@ void dns_restorelock(unsigned int count);
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int dns_bind(sa_family_t family, bool stream);
|
||||
int dns_bind(sa_family_t family, bool stream, int retry_count);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dns_query
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@
|
|||
* server. The name server was previously selected via dns_server().
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
* retry_count - Current retry attempt (0 for first attempt)
|
||||
* stream - Whether to use stream socket
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, the bound, non-negative socket descriptor is returned. A
|
||||
|
|
@ -63,12 +64,30 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int dns_bind(sa_family_t family, bool stream)
|
||||
int dns_bind(sa_family_t family, bool stream, int retry_count)
|
||||
{
|
||||
int stype = stream ? SOCK_STREAM : SOCK_DGRAM;
|
||||
struct timeval tv;
|
||||
int sd;
|
||||
int ret;
|
||||
int timeout_sec;
|
||||
|
||||
/* Calculate progressive timeout: (base timeout * 2^retry_count)
|
||||
* For retry_count 0: base timeout, 1: base*2, 2: base*4, etc.
|
||||
*/
|
||||
|
||||
timeout_sec = CONFIG_NETDB_DNSCLIENT_RECV_TIMEOUT;
|
||||
if (retry_count > 0)
|
||||
{
|
||||
/* Apply exponential backoff with configurable maximum */
|
||||
|
||||
timeout_sec = timeout_sec << retry_count;
|
||||
if (CONFIG_NETDB_DNSCLIENT_MAX_TIMEOUT > 0 &&
|
||||
timeout_sec > CONFIG_NETDB_DNSCLIENT_MAX_TIMEOUT)
|
||||
{
|
||||
timeout_sec = CONFIG_NETDB_DNSCLIENT_MAX_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a new socket */
|
||||
|
||||
|
|
@ -80,17 +99,17 @@ int dns_bind(sa_family_t family, bool stream)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Set up a receive timeout */
|
||||
/* Set up a receive timeout with progressive strategy */
|
||||
|
||||
tv.tv_sec = CONFIG_NETDB_DNSCLIENT_RECV_TIMEOUT;
|
||||
tv.tv_sec = timeout_sec;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
|
||||
if (ret >= 0)
|
||||
{
|
||||
/* Set up a send timeout */
|
||||
/* Set up a send timeout (same progressive strategy) */
|
||||
|
||||
tv.tv_sec = CONFIG_NETDB_DNSCLIENT_SEND_TIMEOUT;
|
||||
tv.tv_sec = timeout_sec;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
ret = setsockopt(sd, SOL_SOCKET, SO_SNDTIMEO, &tv,
|
||||
|
|
|
|||
|
|
@ -854,20 +854,23 @@ static int dns_query_callback(FAR void *arg, FAR struct sockaddr *addr,
|
|||
bool stream = false;
|
||||
|
||||
/* Loop while receive timeout errors occur and there are remaining
|
||||
* retries.
|
||||
* retries. Use progressive timeout strategy.
|
||||
*/
|
||||
|
||||
for (retries = 0; retries < CONFIG_NETDB_DNSCLIENT_RETRIES; retries++)
|
||||
{
|
||||
bool should_try_stream;
|
||||
|
||||
ninfo("INFO: DNS query retry %d/%d\n",
|
||||
retries + 1, CONFIG_NETDB_DNSCLIENT_RETRIES);
|
||||
|
||||
try_stream:
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (dns_is_queryfamily(AF_INET6))
|
||||
{
|
||||
/* Send the IPv6 query */
|
||||
|
||||
sd = dns_bind(addr->sa_family, stream);
|
||||
sd = dns_bind(addr->sa_family, stream, retries);
|
||||
if (sd < 0)
|
||||
{
|
||||
query->result = sd;
|
||||
|
|
@ -922,7 +925,7 @@ try_stream:
|
|||
{
|
||||
/* Send the IPv4 query */
|
||||
|
||||
sd = dns_bind(addr->sa_family, stream);
|
||||
sd = dns_bind(addr->sa_family, stream, retries);
|
||||
if (sd < 0)
|
||||
{
|
||||
query->result = sd;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue