From 70ad94257db8e3b4ef1a28cdb8b87d3b2398f74d Mon Sep 17 00:00:00 2001 From: Aram Sargsyan Date: Tue, 18 Feb 2025 14:44:29 +0000 Subject: [PATCH] Implement tcp-primaries-timeout 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. --- bin/delv/delv.c | 2 +- bin/named/config.c | 1 + bin/named/server.c | 49 ++++++++++++--- bin/nsupdate/nsupdate.c | 3 +- bin/rndc/rndc.c | 4 +- bin/tests/system/keepalive/tests_keepalive.py | 3 +- doc/arm/reference.rst | 21 +++++++ doc/misc/options | 1 + lib/dns/xfrin.c | 16 +++-- lib/dns/zone.c | 61 +++++++++++++------ lib/isc/include/isc/netmgr.h | 15 ++--- lib/isc/netmgr/netmgr-int.h | 7 ++- lib/isc/netmgr/netmgr.c | 10 ++- lib/isc/netmgr/proxystream.c | 3 +- lib/isc/netmgr/proxyudp.c | 3 +- lib/isc/netmgr/streamdns.c | 8 ++- lib/isccfg/namedconf.c | 1 + lib/ns/client.c | 2 +- tests/dns/dispatch_test.c | 8 ++- tests/isc/doh_test.c | 2 +- tests/isc/netmgr_common.c | 8 +-- tests/isc/netmgr_common.h | 9 +-- tests/isc/tcpdns_test.c | 2 +- tests/isc/tlsdns_test.c | 2 +- 24 files changed, 167 insertions(+), 74 deletions(-) diff --git a/bin/delv/delv.c b/bin/delv/delv.c index dbf98ce2b7..041254bb1a 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -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, diff --git a/bin/named/config.c b/bin/named/config.c index c3bc87b0ab..eb93c8a5f3 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -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 \n\ diff --git a/bin/named/server.c b/bin/named/server.c index 910b09a728..fa428f62d1 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -173,6 +173,8 @@ #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) { diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index e42596bc0d..9b087a0ad0 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -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); diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 67b1998bf8..95a5f6a6cf 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -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); diff --git a/bin/tests/system/keepalive/tests_keepalive.py b/bin/tests/system/keepalive/tests_keepalive.py index c815c3e84b..f800898cdb 100644 --- a/bin/tests/system/keepalive/tests_keepalive.py +++ b/bin/tests/system/keepalive/tests_keepalive.py @@ -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" ) diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index b36725487b..35c65fe035 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -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. diff --git a/doc/misc/options b/doc/misc/options index 55f4afb3fa..0d05d4f939 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -297,6 +297,7 @@ options { tcp-initial-timeout ; tcp-keepalive-timeout ; tcp-listen-queue ; + tcp-primaries-timeout ; tcp-receive-buffer ; tcp-send-buffer ; tkey-domain ; diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index 6751c9c99f..243222b5e5 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -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)); diff --git a/lib/dns/zone.c b/lib/dns/zone.c index db84239ca5..769b00420a 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -158,6 +159,10 @@ #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); diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index 887e256519..3fff80d5c6 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -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 diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index fb49de7879..5534e7bdb4 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -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 diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 74d67e0e5d..312c1a3a04 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -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 diff --git a/lib/isc/netmgr/proxystream.c b/lib/isc/netmgr/proxystream.c index 8d65ea5444..65bb9df42f 100644 --- a/lib/isc/netmgr/proxystream.c +++ b/lib/isc/netmgr/proxystream.c @@ -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; diff --git a/lib/isc/netmgr/proxyudp.c b/lib/isc/netmgr/proxyudp.c index 725f873460..6d4359264d 100644 --- a/lib/isc/netmgr/proxyudp.c +++ b/lib/isc/netmgr/proxyudp.c @@ -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; diff --git a/lib/isc/netmgr/streamdns.c b/lib/isc/netmgr/streamdns.c index c80b2285c9..2a8007254f 100644 --- a/lib/isc/netmgr/streamdns.c +++ b/lib/isc/netmgr/streamdns.c @@ -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); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 72b317db15..c2c5ae2899 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -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 }, diff --git a/lib/ns/client.c b/lib/ns/client.c index 214e440440..d5934c0883 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -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); diff --git a/tests/dns/dispatch_test.c b/tests/dns/dispatch_test.c index ae3bed56db..54ebd6f8da 100644 --- a/tests/dns/dispatch_test.c +++ b/tests/dns/dispatch_test.c @@ -44,11 +44,13 @@ #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; diff --git a/tests/isc/doh_test.c b/tests/isc/doh_test.c index 5b98989bef..4b52b3ac36 100644 --- a/tests/isc/doh_test.c +++ b/tests/isc/doh_test.c @@ -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, diff --git a/tests/isc/netmgr_common.c b/tests/isc/netmgr_common.c index 7372af4ab0..cc8d324aeb 100644 --- a/tests/isc/netmgr_common.c +++ b/tests/isc/netmgr_common.c @@ -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); } diff --git a/tests/isc/netmgr_common.h b/tests/isc/netmgr_common.h index c010a320ea..d5cf4b34c9 100644 --- a/tests/isc/netmgr_common.h +++ b/tests/isc/netmgr_common.h @@ -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); diff --git a/tests/isc/tcpdns_test.c b/tests/isc/tcpdns_test.c index b0d213f4bd..30ffdda463 100644 --- a/tests/isc/tcpdns_test.c +++ b/tests/isc/tcpdns_test.c @@ -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); } diff --git a/tests/isc/tlsdns_test.c b/tests/isc/tlsdns_test.c index 831c8c1d26..69acc31e6c 100644 --- a/tests/isc/tlsdns_test.c +++ b/tests/isc/tlsdns_test.c @@ -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,