This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push: new 7b3913da607 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) 7b3913da607 is described below commit 7b3913da607f5f733e0f7cf099242336b5adfaa9 Author: nuttxs <zhaoqing.zh...@sony.com> AuthorDate: Tue Aug 5 17:56:14 2025 +0800 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.zh...@sony.com> --- libs/libc/netdb/Kconfig | 11 ++++++++++- libs/libc/netdb/lib_dns.h | 6 ++++-- libs/libc/netdb/lib_dnsbind.c | 31 +++++++++++++++++++++++++------ libs/libc/netdb/lib_dnsquery.c | 9 ++++++--- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/libs/libc/netdb/Kconfig b/libs/libc/netdb/Kconfig index cf125f4c2b1..86d9746e603 100644 --- a/libs/libc/netdb/Kconfig +++ b/libs/libc/netdb/Kconfig @@ -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 diff --git a/libs/libc/netdb/lib_dns.h b/libs/libc/netdb/lib_dns.h index a42d7909cb6..30ae6a742a3 100644 --- a/libs/libc/netdb/lib_dns.h +++ b/libs/libc/netdb/lib_dns.h @@ -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 diff --git a/libs/libc/netdb/lib_dnsbind.c b/libs/libc/netdb/lib_dnsbind.c index 3b8017b6d5a..10ced32eea0 100644 --- a/libs/libc/netdb/lib_dnsbind.c +++ b/libs/libc/netdb/lib_dnsbind.c @@ -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, diff --git a/libs/libc/netdb/lib_dnsquery.c b/libs/libc/netdb/lib_dnsquery.c index f7bb8e0a4ae..735e94fcfc4 100644 --- a/libs/libc/netdb/lib_dnsquery.c +++ b/libs/libc/netdb/lib_dnsquery.c @@ -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;