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;

Reply via email to