]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Implement tcp-primaries-timeout
authorAram Sargsyan <aram@isc.org>
Tue, 18 Feb 2025 14:44:29 +0000 (14:44 +0000)
committerArаm Sаrgsyаn <aram@isc.org>
Wed, 23 Apr 2025 17:03:05 +0000 (17:03 +0000)
The new 'tcp-primaries-timeout' configuration option works the same way
as the existing 'tcp-initial-timeout' option, but applies only to the
TCP connections made to the primary servers, so that the timeout value
can be set separately for them. The default is 15 seconds.

Also, while accommodating zone.c's code to support the new option, make
a light refactoring with the way UDP timeouts are calculated by using
definitions instead of hardcoded values.

24 files changed:
bin/delv/delv.c
bin/named/config.c
bin/named/server.c
bin/nsupdate/nsupdate.c
bin/rndc/rndc.c
bin/tests/system/keepalive/tests_keepalive.py
doc/arm/reference.rst
doc/misc/options
lib/dns/xfrin.c
lib/dns/zone.c
lib/isc/include/isc/netmgr.h
lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/netmgr.c
lib/isc/netmgr/proxystream.c
lib/isc/netmgr/proxyudp.c
lib/isc/netmgr/streamdns.c
lib/isccfg/namedconf.c
lib/ns/client.c
tests/dns/dispatch_test.c
tests/isc/doh_test.c
tests/isc/netmgr_common.c
tests/isc/netmgr_common.h
tests/isc/tcpdns_test.c
tests/isc/tlsdns_test.c

index dbf98ce2b7bf7d0c8fe5b4e565e852fa1bf478ea..041254bb1a001ba14f9b8846bf1ddf3e610bb0c8 100644 (file)
@@ -2097,7 +2097,7 @@ sendquery(void *arg) {
        dns_view_attach(view, &(dns_view_t *){ NULL });
 
        uint32_t initial;
-       isc_nm_gettimeouts(netmgr, &initial, NULL, NULL, NULL);
+       isc_nm_gettimeouts(netmgr, &initial, NULL, NULL, NULL, NULL);
        const unsigned int connect_timeout = initial, timeout = initial;
 
        CHECK(dns_request_create(requestmgr, message, NULL, &peer, NULL, NULL,
index c3bc87b0abf1bc2d1fe5bab56623cb5de8ee5b4a..eb93c8a5f3f2e87cf8d7562f84488e1268ee0924 100644 (file)
@@ -121,6 +121,7 @@ options {\n\
        tcp-initial-timeout 300;\n\
        tcp-keepalive-timeout 300;\n\
        tcp-listen-queue 10;\n\
+       tcp-primaries-timeout 150;\n\
        tcp-receive-buffer 0;\n\
        tcp-send-buffer 0;\n\
 #      tkey-domain <none>\n\
index 910b09a7280a5d99f413897d4bc1693efbc7ce75..fa428f62d1e56d9ddc4fc5df229b6679947e9a6f 100644 (file)
 #define MAX_KEEPALIVE_TIMEOUT  UINT32_C(UINT16_MAX * 100)
 #define MIN_ADVERTISED_TIMEOUT UINT32_C(0) /* No minimum */
 #define MAX_ADVERTISED_TIMEOUT UINT32_C(UINT16_MAX * 100)
+#define MIN_PRIMARIES_TIMEOUT  UINT32_C(2500)  /* 2.5 seconds */
+#define MAX_PRIMARIES_TIMEOUT  UINT32_C(120000) /* 2 minutes */
 
 /*%
  * Check an operation for failure.  Assumes that the function
@@ -7885,7 +7887,7 @@ load_configuration(const char *filename, named_server_t *server,
        ns_altsecretlist_t altsecrets, tmpaltsecrets;
        uint32_t softquota = 0;
        uint32_t max;
-       uint64_t initial, idle, keepalive, advertised;
+       uint64_t initial, idle, keepalive, advertised, primaries;
        bool loadbalancesockets;
        bool exclusive = true;
        dns_aclenv_t *env =
@@ -8224,8 +8226,26 @@ load_configuration(const char *filename, named_server_t *server,
                advertised = MAX_ADVERTISED_TIMEOUT;
        }
 
-       isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive,
-                          advertised);
+       obj = NULL;
+       result = named_config_get(maps, "tcp-primaries-timeout", &obj);
+       INSIST(result == ISC_R_SUCCESS);
+       primaries = cfg_obj_asuint32(obj) * 100;
+       if (primaries > MAX_PRIMARIES_TIMEOUT) {
+               cfg_obj_log(obj, ISC_LOG_WARNING,
+                           "tcp-primaries-timeout value is out of range: "
+                           "lowering to %" PRIu32,
+                           MAX_PRIMARIES_TIMEOUT / 100);
+               primaries = MAX_PRIMARIES_TIMEOUT;
+       } else if (primaries < MIN_PRIMARIES_TIMEOUT) {
+               cfg_obj_log(obj, ISC_LOG_WARNING,
+                           "tcp-primaries-timeout value is out of range: "
+                           "raising to %" PRIu32,
+                           MIN_PRIMARIES_TIMEOUT / 100);
+               primaries = MIN_PRIMARIES_TIMEOUT;
+       }
+
+       isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive, advertised,
+                          primaries);
 
 #define CAP_IF_NOT_ZERO(v, min, max) \
        if (v > 0 && v < min) {      \
@@ -15740,7 +15760,7 @@ isc_result_t
 named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) {
        char *ptr;
        isc_result_t result = ISC_R_SUCCESS;
-       uint32_t initial, idle, keepalive, advertised;
+       uint32_t initial, idle, keepalive, advertised, primaries;
        char msg[128];
 
        /* Skip the command name. */
@@ -15750,7 +15770,7 @@ named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) {
        }
 
        isc_nm_gettimeouts(named_g_netmgr, &initial, &idle, &keepalive,
-                          &advertised);
+                          &advertised, &primaries);
 
        /* Look for optional arguments. */
        ptr = next_token(lex, NULL);
@@ -15800,8 +15820,21 @@ named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) {
                        CHECK(ISC_R_RANGE);
                }
 
+               ptr = next_token(lex, text);
+               if (ptr == NULL) {
+                       return ISC_R_UNEXPECTEDEND;
+               }
+               CHECK(isc_parse_uint32(&primaries, ptr, 10));
+               primaries *= 100;
+               if (primaries > MAX_PRIMARIES_TIMEOUT) {
+                       CHECK(ISC_R_RANGE);
+               }
+               if (primaries < MIN_PRIMARIES_TIMEOUT) {
+                       CHECK(ISC_R_RANGE);
+               }
+
                isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive,
-                                  advertised);
+                                  advertised, primaries);
        }
 
        snprintf(msg, sizeof(msg), "tcp-initial-timeout=%u\n", initial / 100);
@@ -15811,9 +15844,11 @@ named_server_tcptimeouts(isc_lex_t *lex, isc_buffer_t **text) {
        snprintf(msg, sizeof(msg), "tcp-keepalive-timeout=%u\n",
                 keepalive / 100);
        CHECK(putstr(text, msg));
-       snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u",
+       snprintf(msg, sizeof(msg), "tcp-advertised-timeout=%u\n",
                 advertised / 100);
        CHECK(putstr(text, msg));
+       snprintf(msg, sizeof(msg), "tcp-primaries-timeout=%u", primaries / 100);
+       CHECK(putstr(text, msg));
 
 cleanup:
        if (isc_buffer_usedlength(*text) > 0) {
index e42596bc0db71d4e9d7c8dbdabcf6055c2862624..9b087a0ad0079c53d50d73777af299f790d29a4f 100644 (file)
@@ -3532,7 +3532,8 @@ main(int argc, char **argv) {
 
        /* Set the network manager timeouts in milliseconds. */
        timeoutms = timeout * 1000;
-       isc_nm_settimeouts(netmgr, timeoutms, timeoutms, timeoutms, timeoutms);
+       isc_nm_settimeouts(netmgr, timeoutms, timeoutms, timeoutms, timeoutms,
+                          timeoutms);
 
        isc_loopmgr_setup(loopmgr, setup_system, NULL);
        isc_loopmgr_setup(loopmgr, getinput, NULL);
index 67b1998bf8d98b3a406a3da45d158b4072c95fc1..95a5f6a6cf4f8203664e86baf6018980f2e5bfb0 100644 (file)
@@ -221,7 +221,7 @@ command is one of the following:\n\
                Dump a single zone's changes to disk, and optionally\n\
                remove its journal file.\n\
   tcp-timeouts Display the tcp-*-timeout option values\n\
-  tcp-timeouts initial idle keepalive advertised\n\
+  tcp-timeouts initial idle keepalive advertised primaries\n\
                Update the tcp-*-timeout option values\n\
   thaw         Enable updates to all dynamic zones and reload them.\n\
   thaw zone [class [view]]\n\
@@ -966,7 +966,7 @@ main(int argc, char **argv) {
        isc_managers_create(&rndc_mctx, 1, &loopmgr, &netmgr);
        isc_loopmgr_setup(loopmgr, rndc_start, NULL);
 
-       isc_nm_settimeouts(netmgr, timeout, timeout, timeout, 0);
+       isc_nm_settimeouts(netmgr, timeout, timeout, timeout, 0, timeout);
 
        logconfig = isc_logconfig_get();
        isc_log_settag(logconfig, progname);
index c815c3e84b84c0982ddf5fcf1597bd555b1635b3..f800898cdb8a11f04710b4b3977efd6893871bf8 100644 (file)
@@ -53,11 +53,12 @@ def test_dig_tcp_keepalive_handling(named_port, servers):
     )
 
     isctest.log.info("check a re-configured keepalive value")
-    response = servers["ns2"].rndc("tcp-timeouts 300 300 300 200", log=False)
+    response = servers["ns2"].rndc("tcp-timeouts 300 300 300 200 100", log=False)
     assert "tcp-initial-timeout=300" in response
     assert "tcp-idle-timeout=300" in response
     assert "tcp-keepalive-timeout=300" in response
     assert "tcp-advertised-timeout=200" in response
+    assert "tcp-primaries-timeout=100" in response
     assert "; TCP-KEEPALIVE: 20.0 secs" in dig(
         "+tcp +keepalive foo.example. @10.53.0.2"
     )
index b36725487b465419f05842489b4aa2a688ad2c9c..35c65fe035368cd5e79ef5fb1cdbd90313a58e60 100644 (file)
@@ -3926,6 +3926,27 @@ system.
    value as :any:`tcp-keepalive-timeout`. This value can be updated at
    runtime by using :option:`rndc tcp-timeouts`.
 
+.. namedconf:statement:: tcp-primaries-timeout
+   :tags: server, query
+   :short: Sets the amount of time (in milliseconds) that the server waits for a successful TCP connection when connecting to a primary server.
+
+   This sets the amount of time, in units of 100 milliseconds, that the server
+   waits when connecting to a primary server. The default is 150 (15 seconds),
+   the minimum is 25 (2.5 seconds), and the maximum is 1200 (two minutes).
+   This value can be updated at runtime by using :option:`rndc tcp-timeouts`.
+
+.. note::
+
+   This value works the same way as :any:`tcp-initial-timeout`, but applies
+   only to the connections to primary servers in order to provide a way to tune
+   it separately if, for example, it is required to try the next server faster.
+
+.. note::
+
+   Depending on the operating system's networking settings, the timeout may
+   occur earlier than the defined value in cases when the system's maximum wait
+   time for a TCP connection is smaller than the defined value.
+
 .. namedconf:statement:: update-quota
    :tags: server
    :short: Specifies the maximum number of concurrent DNS UPDATE messages that can be processed by the server.
index 55f4afb3faa835df62ff2f45607bf9e33e12e443..0d05d4f93957fd0395bf8d2f63a48b1ab07b47cc 100644 (file)
@@ -297,6 +297,7 @@ options {
        tcp-initial-timeout <integer>;
        tcp-keepalive-timeout <integer>;
        tcp-listen-queue <integer>;
+       tcp-primaries-timeout <integer>;
        tcp-receive-buffer <integer>;
        tcp-send-buffer <integer>;
        tkey-domain <quoted_string>;
index 6751c9c99f51df25e9ba913d8daebcf6115c3460..243222b5e5eab477951dcfedd79ecba6b5f38b75 100644 (file)
@@ -1300,7 +1300,7 @@ static isc_result_t
 xfrin_start(dns_xfrin_t *xfr) {
        isc_result_t result = ISC_R_FAILURE;
        isc_interval_t interval;
-       uint32_t initial;
+       uint32_t primaries_timeout;
 
        dns_xfrin_ref(xfr);
 
@@ -1313,8 +1313,8 @@ xfrin_start(dns_xfrin_t *xfr) {
                goto failure;
        }
 
-       isc_nm_gettimeouts(dns_dispatchmgr_getnetmgr(dispmgr), &initial, NULL,
-                          NULL, NULL);
+       isc_nm_gettimeouts(dns_dispatchmgr_getnetmgr(dispmgr), NULL, NULL, NULL,
+                          NULL, &primaries_timeout);
        result = dns_dispatch_createtcp(dispmgr, &xfr->sourceaddr,
                                        &xfr->primaryaddr, xfr->transport,
                                        DNS_DISPATCHOPT_UNSHARED, &xfr->disp);
@@ -1344,15 +1344,13 @@ xfrin_start(dns_xfrin_t *xfr) {
        }
 
        /*
-        * Before a configuration option for the primary servers' TCP timeout
-        * is implemented, use initial TCP timeout as the connect timeout.
-        * The receive timeout timer is disabled on the dispatch level because
+        * The read timeout timer is disabled on the dispatch level because
         * the xfr module has its own timeouts.
         */
-       const unsigned int connect_timeout = initial, timeout = 0;
+       const unsigned int read_timeout = 0;
 
-       CHECK(dns_dispatch_add(xfr->disp, xfr->loop, 0, connect_timeout,
-                              timeout, &xfr->primaryaddr, xfr->transport,
+       CHECK(dns_dispatch_add(xfr->disp, xfr->loop, 0, primaries_timeout,
+                              read_timeout, &xfr->primaryaddr, xfr->transport,
                               xfr->tlsctx_cache, xfrin_connect_done,
                               xfrin_send_done, xfrin_recv_done, xfr, &xfr->id,
                               &xfr->dispentry));
index db84239ca55a0f6c4ed266dd17fe0c218089a7ac..769b00420ad9fe112700cfdc5c5d12aeb18992c7 100644 (file)
@@ -27,6 +27,7 @@
 #include <isc/loop.h>
 #include <isc/md.h>
 #include <isc/mutex.h>
+#include <isc/netmgr.h>
 #include <isc/overflow.h>
 #include <isc/random.h>
 #include <isc/ratelimiter.h>
 #define DNS_DEFAULT_IDLEOUT 3600       /*%< 1 hour */
 #define MAX_XFER_TIME      (2 * 3600) /*%< Documented default is 2 hours */
 #define RESIGN_DELAY       3600       /*%< 1 hour */
+#define UDP_REQUEST_TIMEOUT 5         /*%< 5 seconds */
+#define UDP_REQUEST_RETRIES 2
+#define TCP_REQUEST_TIMEOUT \
+       (UDP_REQUEST_TIMEOUT * (UDP_REQUEST_RETRIES + 1) + 1)
 
 #ifndef DNS_MAX_EXPIRE
 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
@@ -1083,7 +1088,8 @@ struct stub_cb_args {
        dns_stub_t *stub;
        dns_tsigkey_t *tsig_key;
        uint16_t udpsize;
-       int timeout;
+       unsigned int connect_timeout;
+       unsigned int timeout;
        bool reqnsid;
 };
 
@@ -12722,8 +12728,10 @@ notify_send_toaddr(void *arg) {
                result = ISC_R_NOTIMPLEMENTED;
                goto cleanup_key;
        }
+
        udptimeout = 5;
        connect_timeout = timeout = 3 * udptimeout + 1;
+
 again:
        if ((notify->flags & DNS_NOTIFY_TCP) != 0) {
                options |= DNS_REQUESTOPT_TCP;
@@ -13481,8 +13489,9 @@ stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
        result = dns_request_create(
                zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
                NULL, NULL, DNS_REQUESTOPT_TCP, args->tsig_key,
-               args->timeout * 3 + 1, args->timeout * 3 + 1, args->timeout, 2,
-               zone->loop, stub_glue_response, sgr, &sgr->request);
+               args->connect_timeout, args->timeout, UDP_REQUEST_TIMEOUT,
+               UDP_REQUEST_RETRIES, zone->loop, stub_glue_response, sgr,
+               &sgr->request);
 
        if (result != ISC_R_SUCCESS) {
                uint_fast32_t pr;
@@ -14631,13 +14640,17 @@ again:
                }
        }
 
-       zone_iattach(zone, &(dns_zone_t *){ NULL });
+       uint32_t primaries_timeout;
+       isc_nm_gettimeouts(zone->zmgr->netmgr, NULL, NULL, NULL, NULL,
+                          &primaries_timeout);
+       const unsigned int connect_timeout = primaries_timeout / MS_PER_SEC;
 
-       const unsigned int timeout = 5;
+       zone_iattach(zone, &(dns_zone_t *){ NULL });
        result = dns_request_create(
                zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
-               NULL, NULL, options, key, timeout * 3 + 1, timeout * 3 + 1,
-               timeout, 2, zone->loop, refresh_callback, zone, &zone->request);
+               NULL, NULL, options, key, connect_timeout, TCP_REQUEST_TIMEOUT,
+               UDP_REQUEST_TIMEOUT, UDP_REQUEST_RETRIES, zone->loop,
+               refresh_callback, zone, &zone->request);
        if (result != ISC_R_SUCCESS) {
                zone_idetach(&(dns_zone_t *){ zone });
                zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
@@ -14898,6 +14911,11 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
                goto cleanup;
        }
 
+       uint32_t primaries_timeout;
+       isc_nm_gettimeouts(zone->zmgr->netmgr, NULL, NULL, NULL, NULL,
+                          &primaries_timeout);
+       const unsigned int connect_timeout = primaries_timeout / MS_PER_SEC;
+
        /*
         * Save request parameters so we can reuse them later on
         * for resolving missing glue A/AAAA records.
@@ -14906,15 +14924,15 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
        cb_args->stub = stub;
        cb_args->tsig_key = key;
        cb_args->udpsize = udpsize;
-       cb_args->timeout = 15;
+       cb_args->connect_timeout = connect_timeout;
+       cb_args->timeout = TCP_REQUEST_TIMEOUT;
        cb_args->reqnsid = reqnsid;
 
-       const unsigned int timeout = 5;
-       result = dns_request_create(zone->view->requestmgr, message,
-                                   &zone->sourceaddr, &curraddr, NULL, NULL,
-                                   DNS_REQUESTOPT_TCP, key, timeout * 3 + 1,
-                                   timeout * 3 + 1, timeout, 2, zone->loop,
-                                   stub_callback, cb_args, &zone->request);
+       result = dns_request_create(
+               zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
+               NULL, NULL, DNS_REQUESTOPT_TCP, key, connect_timeout,
+               TCP_REQUEST_TIMEOUT, UDP_REQUEST_TIMEOUT, UDP_REQUEST_RETRIES,
+               zone->loop, stub_callback, cb_args, &zone->request);
        if (result != ISC_R_SUCCESS) {
                zone_debuglog(zone, __func__, 1,
                              "dns_request_create() failed: %s",
@@ -18718,10 +18736,7 @@ next:
        }
 
        /*
-        * Always use TCP regardless of whether the original update
-        * used TCP.
-        * XXX The timeout may but a bit small if we are far down a
-        * transfer graph and have to try several primaries.
+        * Always use TCP regardless of whether the original update used TCP.
         */
        switch (isc_sockaddr_pf(&forward->addr)) {
        case PF_INET:
@@ -18763,13 +18778,19 @@ next:
                }
        }
 
+       uint32_t primaries_timeout;
+       isc_nm_gettimeouts(zone->zmgr->netmgr, NULL, NULL, NULL, NULL,
+                          &primaries_timeout);
+       const unsigned int connect_timeout = primaries_timeout / MS_PER_SEC;
+
        zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
 
        result = dns_request_createraw(
                forward->zone->view->requestmgr, forward->msgbuf, &src,
                &forward->addr, forward->transport, zmgr_tlsctx_cache,
-               forward->options, 15, 15 /* XXX */, 0, 0, forward->zone->loop,
-               forward_callback, forward, &forward->request);
+               forward->options, connect_timeout, TCP_REQUEST_TIMEOUT, 0, 0,
+               forward->zone->loop, forward_callback, forward,
+               &forward->request);
 
        isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
 
index 887e256519603d8f49f4f26ce259210774c7e350..3fff80d5c60fb95a4abb8db5bf983d6e0267c024 100644 (file)
@@ -537,12 +537,12 @@ isc_nm_proxyheader_info_init_complete(isc_nm_proxyheader_info_t *restrict info,
 
 void
 isc_nm_settimeouts(isc_nm_t *mgr, uint32_t init, uint32_t idle,
-                  uint32_t keepalive, uint32_t advertised);
+                  uint32_t keepalive, uint32_t advertised, uint32_t primaries);
 /*%<
- * Sets the initial, idle, and keepalive timeout values (in milliseconds) to use
- * for TCP connections, and the timeout value to advertise in responses using
- * the EDNS TCP Keepalive option (which should ordinarily be the same
- * as 'keepalive'), in milliseconds.
+ * Sets the initial, idle, keepalive, advertised, and primaries timeout values
+ * (in milliseconds) to use for TCP connections, and the timeout value to
+ * advertise in responses using the EDNS TCP Keepalive option (which should
+ * ordinarily be the same as 'keepalive'), in milliseconds.
  *
  * Requires:
  * \li 'mgr' is a valid netmgr.
@@ -572,9 +572,10 @@ isc_nm_setloadbalancesockets(isc_nm_t *mgr, bool enabled);
 
 void
 isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle,
-                  uint32_t *keepalive, uint32_t *advertised);
+                  uint32_t *keepalive, uint32_t *advertised,
+                  uint32_t *primaries);
 /*%<
- * Gets the initial, idle, keepalive, or advertised timeout values,
+ * Gets the initial, idle, keepalive, advertised, or primaries timeout values,
  * in milliseconds.
  *
  * Any integer pointer parameter not set to NULL will be updated to
index fb49de78799a5cd33301132669030f67c114255e..5534e7bdb4d48990b1ec43c17e22ca945ba77a39 100644 (file)
@@ -349,14 +349,15 @@ struct isc_nm {
        /*
         * Timeout values for TCP connections, corresponding to
         * tcp-intiial-timeout, tcp-idle-timeout, tcp-keepalive-timeout,
-        * and tcp-advertised-timeout. Note that these are stored in
-        * milliseconds so they can be used directly with the libuv timer,
-        * but they are configured in tenths of seconds.
+        * tcp-advertised-timeout, and tcp-primaries-timeout. Note that these
+        * are stored in milliseconds so they can be used directly with the
+        * libuv timer, but they are configured in tenths of seconds.
         */
        atomic_uint_fast32_t init;
        atomic_uint_fast32_t idle;
        atomic_uint_fast32_t keepalive;
        atomic_uint_fast32_t advertised;
+       atomic_uint_fast32_t primaries;
 
        /*
         * Socket SO_RCVBUF and SO_SNDBUF values
index 74d67e0e5d89dfef22358cb3ffe68f60d4044d47..312c1a3a04fe34594b61d9e5b81bab3191551fc8 100644 (file)
@@ -199,6 +199,7 @@ isc_netmgr_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, isc_nm_t **netmgrp) {
        atomic_init(&netmgr->idle, 30000);
        atomic_init(&netmgr->keepalive, 30000);
        atomic_init(&netmgr->advertised, 30000);
+       atomic_init(&netmgr->primaries, 30000);
 
        netmgr->workers = isc_mem_cget(mctx, netmgr->nloops,
                                       sizeof(netmgr->workers[0]));
@@ -338,13 +339,15 @@ isc_nmhandle_setwritetimeout(isc_nmhandle_t *handle, uint64_t write_timeout) {
 
 void
 isc_nm_settimeouts(isc_nm_t *mgr, uint32_t init, uint32_t idle,
-                  uint32_t keepalive, uint32_t advertised) {
+                  uint32_t keepalive, uint32_t advertised,
+                  uint32_t primaries) {
        REQUIRE(VALID_NM(mgr));
 
        atomic_store_relaxed(&mgr->init, init);
        atomic_store_relaxed(&mgr->idle, idle);
        atomic_store_relaxed(&mgr->keepalive, keepalive);
        atomic_store_relaxed(&mgr->advertised, advertised);
+       atomic_store_relaxed(&mgr->primaries, primaries);
 }
 
 void
@@ -376,7 +379,8 @@ isc_nm_setloadbalancesockets(isc_nm_t *mgr, ISC_ATTR_UNUSED bool enabled) {
 
 void
 isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle,
-                  uint32_t *keepalive, uint32_t *advertised) {
+                  uint32_t *keepalive, uint32_t *advertised,
+                  uint32_t *primaries) {
        REQUIRE(VALID_NM(mgr));
 
        SET_IF_NOT_NULL(initial, atomic_load_relaxed(&mgr->init));
@@ -386,6 +390,8 @@ isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle,
        SET_IF_NOT_NULL(keepalive, atomic_load_relaxed(&mgr->keepalive));
 
        SET_IF_NOT_NULL(advertised, atomic_load_relaxed(&mgr->advertised));
+
+       SET_IF_NOT_NULL(primaries, atomic_load_relaxed(&mgr->primaries));
 }
 
 bool
index 8d65ea544480042bbaacbcff76983a8fa168f16c..65bb9df42f833262ad39e0b01b250903dccbaf7e 100644 (file)
@@ -242,7 +242,8 @@ proxystream_sock_new(isc__networker_t *worker, const isc_nmsocket_type_t type,
        sock->result = ISC_R_UNSET;
        if (type == isc_nm_proxystreamsocket) {
                uint32_t initial = 0;
-               isc_nm_gettimeouts(worker->netmgr, &initial, NULL, NULL, NULL);
+               isc_nm_gettimeouts(worker->netmgr, &initial, NULL, NULL, NULL,
+                                  NULL);
                sock->read_timeout = initial;
                sock->client = !is_server;
                sock->connecting = !is_server;
index 725f8734602f2e4db372f966fd2ffba9e92cefeb..6d4359264daaebeddfe56511e8227e50513a60e1 100644 (file)
@@ -214,7 +214,8 @@ proxyudp_sock_new(isc__networker_t *worker, const isc_nmsocket_type_t type,
        sock->result = ISC_R_UNSET;
        if (type == isc_nm_proxyudpsocket) {
                uint32_t initial = 0;
-               isc_nm_gettimeouts(worker->netmgr, &initial, NULL, NULL, NULL);
+               isc_nm_gettimeouts(worker->netmgr, &initial, NULL, NULL, NULL,
+                                  NULL);
                sock->read_timeout = initial;
                sock->client = !is_server;
                sock->connecting = !is_server;
index c80b2285c901d0542309166b9c44b1efe966b3dd..2a8007254f37d363615ddf7a92ebf38084602b36 100644 (file)
@@ -272,7 +272,8 @@ streamdns_sock_new(isc__networker_t *worker, const isc_nmsocket_type_t type,
        sock->result = ISC_R_UNSET;
        if (type == isc_nm_streamdnssocket) {
                uint32_t initial = 0;
-               isc_nm_gettimeouts(worker->netmgr, &initial, NULL, NULL, NULL);
+               isc_nm_gettimeouts(worker->netmgr, &initial, NULL, NULL, NULL,
+                                  NULL);
                sock->read_timeout = initial;
                sock->client = !is_server;
                sock->connecting = !is_server;
@@ -726,7 +727,7 @@ streamdns_accept_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
        nsock->peer = isc_nmhandle_peeraddr(handle);
        nsock->tid = tid;
        isc_nm_gettimeouts(handle->sock->worker->netmgr, &initial, NULL, NULL,
-                          NULL);
+                          NULL, NULL);
        nsock->read_timeout = initial;
        nsock->accepting = true;
        nsock->active = true;
@@ -751,7 +752,8 @@ streamdns_accept_cb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
 
        nsock->closehandle_cb = streamdns_resume_processing;
        isc__nmhandle_set_manual_timer(nsock->outerhandle, true);
-       isc_nm_gettimeouts(nsock->worker->netmgr, &initial, NULL, NULL, NULL);
+       isc_nm_gettimeouts(nsock->worker->netmgr, &initial, NULL, NULL, NULL,
+                          NULL);
        /* settimeout restarts the timer */
        isc_nmhandle_settimeout(nsock->outerhandle, initial);
        (void)isc_nmhandle_set_tcp_nodelay(nsock->outerhandle, true);
index 72b317db159355184536016a2187cef221c22347..c2c5ae28991583700bb936f5089d794488142f10 100644 (file)
@@ -1329,6 +1329,7 @@ static cfg_clausedef_t options_clauses[] = {
        { "tcp-initial-timeout", &cfg_type_uint32, 0 },
        { "tcp-keepalive-timeout", &cfg_type_uint32, 0 },
        { "tcp-listen-queue", &cfg_type_uint32, 0 },
+       { "tcp-primaries-timeout", &cfg_type_uint32, 0 },
        { "tcp-receive-buffer", &cfg_type_uint32, 0 },
        { "tcp-send-buffer", &cfg_type_uint32, 0 },
        { "tkey-dhkey", NULL, CFG_CLAUSEFLAG_ANCIENT },
index 214e440440f29693d2b50257d7b113234f6613d1..d5934c088338ca2d8f0beb7f9c7e2827d7281546 100644 (file)
@@ -1183,7 +1183,7 @@ no_nsid:
                INSIST(count < DNS_EDNSOPTIONS);
 
                isc_nm_gettimeouts(isc_nmhandle_netmgr(client->handle), NULL,
-                                  NULL, NULL, &adv);
+                                  NULL, NULL, &adv, NULL);
                adv /= 100; /* units of 100 milliseconds */
                isc_buffer_init(&buf, advtimo, sizeof(advtimo));
                isc_buffer_putuint16(&buf, (uint16_t)adv);
index ae3bed56db76000b83a3ea63d159e7b6c6209476..54ebd6f8dab3f5929e58646643c93ba74ffb237a 100644 (file)
 #define T_SERVER_IDLE      (120 * 1000)
 #define T_SERVER_KEEPALIVE  (120 * 1000)
 #define T_SERVER_ADVERTISED (120 * 1000)
+#define T_SERVER_PRIMARIES  (120 * 1000)
 
 #define T_CLIENT_INIT      (60 * 1000)
 #define T_CLIENT_IDLE      (60 * 1000)
 #define T_CLIENT_KEEPALIVE  (60 * 1000)
 #define T_CLIENT_ADVERTISED (60 * 1000)
+#define T_CLIENT_PRIMARIES  (60 * 1000)
 
 #define T_CLIENT_CONNECT (30 * 1000)
 
@@ -194,14 +196,16 @@ setup_test(void **state) {
        close(socket);
 
        isc_nm_settimeouts(netmgr, T_SERVER_INIT, T_SERVER_IDLE,
-                          T_SERVER_KEEPALIVE, T_SERVER_ADVERTISED);
+                          T_SERVER_KEEPALIVE, T_SERVER_ADVERTISED,
+                          T_SERVER_PRIMARIES);
 
        /*
         * Use shorter client-side timeouts, to ensure that clients
         * time out before the server.
         */
        isc_nm_settimeouts(connect_nm, T_CLIENT_INIT, T_CLIENT_IDLE,
-                          T_CLIENT_KEEPALIVE, T_CLIENT_ADVERTISED);
+                          T_CLIENT_KEEPALIVE, T_CLIENT_ADVERTISED,
+                          T_CLIENT_PRIMARIES);
 
        memset(testdata.rbuf, 0, sizeof(testdata.rbuf));
        testdata.region.base = testdata.rbuf;
index 5b98989beface802337e1558304f5ad3a9b9ffcd..4b52b3ac365ed92161329c5e517bfdb19335a24a 100644 (file)
@@ -693,7 +693,7 @@ doh_timeout_recovery(void *arg ISC_ATTR_UNUSED) {
         * Shorten all the TCP client timeouts to 0.05 seconds.
         * timeout_retry_cb() will give up after five timeouts.
         */
-       isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
+       isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
        sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url),
                        ISC_NM_HTTP_DEFAULT_PATH);
        isc_nm_httpconnect(connect_nm, NULL, &tcp_listen_addr, req_url,
index 7372af4ab008d96e7f3edc41c6edbd38f601b9b3..cc8d324aeb8bb61304a76527c451442be6d1cbe3 100644 (file)
@@ -178,13 +178,13 @@ setup_netmgr_test(void **state) {
        setup_loopmgr(state);
        isc_netmgr_create(mctx, loopmgr, &listen_nm);
        assert_non_null(listen_nm);
-       isc_nm_settimeouts(listen_nm, T_INIT, T_IDLE, T_KEEPALIVE,
-                          T_ADVERTISED);
+       isc_nm_settimeouts(listen_nm, T_INIT, T_IDLE, T_KEEPALIVE, T_ADVERTISED,
+                          T_PRIMARIES);
 
        isc_netmgr_create(mctx, loopmgr, &connect_nm);
        assert_non_null(connect_nm);
        isc_nm_settimeouts(connect_nm, T_INIT, T_IDLE, T_KEEPALIVE,
-                          T_ADVERTISED);
+                          T_ADVERTISED, T_PRIMARIES);
 
        isc_quota_init(&listener_quota, 0);
        atomic_store(&check_listener_quota, false);
@@ -1026,7 +1026,7 @@ stream_timeout_recovery(void **state ISC_ATTR_UNUSED) {
        /*
         * Shorten all the client timeouts to 0.05 seconds.
         */
-       isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
+       isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
        connect_readcb = timeout_retry_cb;
        stream_connect(connect_connect_cb, NULL, T_CONNECT);
 }
index c010a320ea935b8d5e4a23ef3af4c6fe0e1219e1..d5cf4b34c9afd523d07a4bc9eb487da7b21d56bd 100644 (file)
@@ -153,6 +153,7 @@ extern isc_nm_recv_cb_t connect_readcb;
 #define T_IDLE      120 * 1000
 #define T_KEEPALIVE  120 * 1000
 #define T_ADVERTISED 120 * 1000
+#define T_PRIMARIES  120 * 1000
 #define T_CONNECT    30 * 1000
 
 /* Wait for 1 second (1000 milliseconds) */
@@ -450,12 +451,8 @@ stop_listening(void *arg ISC_ATTR_UNUSED);
 /* Timeout for soft-timeout tests (0.05 seconds) */
 #define UDP_T_SOFT 50
 
-/* Timeouts in miliseconds */
-#define UDP_T_INIT      120 * 1000
-#define UDP_T_IDLE      120 * 1000
-#define UDP_T_KEEPALIVE         120 * 1000
-#define UDP_T_ADVERTISED 120 * 1000
-#define UDP_T_CONNECT   30 * 1000
+/* Timeout in miliseconds */
+#define UDP_T_CONNECT 30 * 1000
 
 int
 setup_udp_test(void **state);
index b0d213f4bdcc5a94d9b5ffcb71d4b3e11b5b26fe..30ffdda463f8efa23cd7a7ce6dc33f8dd1377ff3 100644 (file)
@@ -100,7 +100,7 @@ ISC_LOOP_TEST_IMPL(tcpdns_timeout_recovery) {
         * timeout_retry_cb() will give up after five timeouts.
         */
        connect_readcb = timeout_retry_cb;
-       isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
+       isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
 
        isc_async_current(stream_recv_send_connect, tcpdns_connect);
 }
index 831c8c1d262774d842aa945d43838243f02c3392..69acc31e6c0559fcee2baf7059d9946ebe7ab792 100644 (file)
@@ -105,7 +105,7 @@ ISC_LOOP_TEST_IMPL(tlsdns_timeout_recovery) {
         * timeout_retry_cb() will give up after five timeouts.
         */
        connect_readcb = timeout_retry_cb;
-       isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
+       isc_nm_settimeouts(connect_nm, T_SOFT, T_SOFT, T_SOFT, T_SOFT, T_SOFT);
        isc_refcount_increment0(&active_cconnects);
        isc_nm_streamdnsconnect(
                connect_nm, &tcp_connect_addr, &tcp_listen_addr,