From f439eb5d99f6ac6650de3c0719e870c31acddd8c Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Thu, 17 Dec 2020 00:43:00 -0800 Subject: [PATCH] Dispatch API simplification - Many dispatch attributes can be set implicitly instead of being passed in. we can infer whether to set DNS_DISPATCHATTR_TCP or _UDP from whether we're calling dns_dispatch_createtcp() or _createudp(). we can also infer DNS_DISPATCHATTR_IPV4 or _IPV6 from the addresses or the socket that were passed in. - We no longer use dup'd sockets in UDP dispatches, so the 'dup_socket' parameter has been removed from dns_dispatch_createudp(), along with the code implementing it. also removed isc_socket_dup() since it no longer has any callers. - The 'buffersize' parameter was ignored and has now been removed; buffersize is now fixed at 4096. - Maxbuffers and maxrequests don't need to be passed in on every call to dns_dispatch_createtcp() and _createudp(). In all current uses, the value for mgr->maxbuffers will either be raised once from its default of 20000 to 32768, or else left alone. (passing in a value lower than 20000 does not lower it.) there isn't enough difference between these values for there to be any need to configure this. The value for disp->maxrequests controls both the quota of concurrent requests for a dispatch and also the size of the dispatch socket memory pool. it's not clear that this quota is necessary at all. the memory pool size currently starts at 32768, but is sometimes lowered to 4096, which is definitely unnecessary. This commit sets both values permanently to 32768. - Previously TCP dispatches allocated their own separate QID table, which didn't incorporate a port table. this commit removes per-dispatch QID tables and shares the same table between all dispatches. since dispatches are created for each TCP socket, this may speed up the dispatch allocation process. there may be a slight increase in lock contention since all dispatches are sharing a single QID table, but since TCP sockets are used less often than UDP sockets (which were already sharing a QID table), it should not be a substantial change. - The dispatch port table was being used to determine whether a port was already in use; if so, then a UDP socket would be bound with REUSEADDR. this commit removes the port table, and always binds UDP sockets that way. --- bin/named/server.c | 37 +- bin/nsupdate/nsupdate.c | 9 +- bin/tests/system/pipelined/pipequeries.c | 9 +- bin/tests/system/tkey/keycreate.c | 33 +- bin/tests/system/tkey/keydelete.c | 33 +- bin/tools/mdig.c | 9 +- lib/dns/client.c | 30 +- lib/dns/dispatch.c | 510 +++++++---------------- lib/dns/include/dns/dispatch.h | 43 +- lib/dns/request.c | 90 +--- lib/dns/resolver.c | 25 +- lib/dns/tests/dispatch_test.c | 8 +- lib/dns/tests/resolver_test.c | 2 +- lib/isc/include/isc/socket.h | 6 - lib/isc/socket.c | 140 +++---- lib/isc/tests/socket_test.c | 85 ---- 16 files changed, 273 insertions(+), 796 deletions(-) diff --git a/bin/named/server.c b/bin/named/server.c index 57930b5040..e70cba3662 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -160,10 +160,8 @@ #ifdef TUNE_LARGE #define RESOLVER_NTASKS_PERCPU 32 -#define UDPBUFFERS 32768 #else #define RESOLVER_NTASKS_PERCPU 8 -#define UDPBUFFERS 4096 #endif /* TUNE_LARGE */ /* RFC7828 defines timeout as 16-bit value specified in units of 100 @@ -1260,9 +1258,8 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, isc_result_t result = ISC_R_FAILURE; dns_dispatch_t *disp = NULL; isc_sockaddr_t sa; - unsigned int attrs; + unsigned int attrs = 0; const cfg_obj_t *obj = NULL; - unsigned int maxdispatchbuffers = UDPBUFFERS; isc_dscp_t dscp = -1; switch (af) { @@ -1308,15 +1305,6 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, /* * Try to find a dispatcher that we can share. */ - attrs = DNS_DISPATCHATTR_UDP; - switch (af) { - case AF_INET: - attrs |= DNS_DISPATCHATTR_IPV4; - break; - case AF_INET6: - attrs |= DNS_DISPATCHATTR_IPV6; - break; - } if (isc_sockaddr_getport(&sa) != 0) { INSIST(obj != NULL); if (is_firstview) { @@ -1327,9 +1315,8 @@ get_view_querysource_dispatch(const cfg_obj_t **maps, int af, } } - result = dns_dispatch_createudp( - named_g_dispatchmgr, named_g_socketmgr, named_g_taskmgr, &sa, - maxdispatchbuffers, 32768, 16411, 16433, attrs, &disp); + result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr, + named_g_taskmgr, &sa, attrs, &disp); if (result != ISC_R_SUCCESS) { isc_sockaddr_t any; char buf[ISC_SOCKADDR_FORMATSIZE]; @@ -10343,7 +10330,7 @@ named_add_reserved_dispatch(named_server_t *server, in_port_t port; char addrbuf[ISC_SOCKADDR_FORMATSIZE]; isc_result_t result; - unsigned int attrs; + unsigned int attrs = 0; REQUIRE(NAMED_SERVER_VALID(server)); @@ -10370,22 +10357,8 @@ named_add_reserved_dispatch(named_server_t *server, dispatch->dispatchgen = server->dispatchgen; dispatch->dispatch = NULL; - attrs = DNS_DISPATCHATTR_UDP; - switch (isc_sockaddr_pf(addr)) { - case AF_INET: - attrs |= DNS_DISPATCHATTR_IPV4; - break; - case AF_INET6: - attrs |= DNS_DISPATCHATTR_IPV6; - break; - default: - result = ISC_R_NOTIMPLEMENTED; - goto cleanup; - } - result = dns_dispatch_createudp(named_g_dispatchmgr, named_g_socketmgr, - named_g_taskmgr, &dispatch->addr, - UDPBUFFERS, 32768, 16411, 16433, attrs, + named_g_taskmgr, &dispatch->addr, attrs, &dispatch->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup; diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index d0a2895d01..be39164216 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -801,7 +801,6 @@ static void setup_system(void) { isc_result_t result; isc_sockaddr_t bind_any, bind_any6; - unsigned int attrs; isc_sockaddrlist_t *nslist; isc_logconfig_t *logconfig = NULL; irs_resconf_t *resconf = NULL; @@ -937,20 +936,16 @@ setup_system(void) { set_source_ports(dispatchmgr); if (have_ipv6) { - attrs = (DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV6); isc_sockaddr_any6(&bind_any6); result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - &bind_any6, 4, 2, 3, 5, attrs, - &dispatchv6); + &bind_any6, 0, &dispatchv6); check_result(result, "dns_dispatch_createudp (v6)"); } if (have_ipv4) { - attrs = (DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4); isc_sockaddr_any(&bind_any); result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - &bind_any, 4, 2, 3, 5, attrs, - &dispatchv4); + &bind_any, 0, &dispatchv4); check_result(result, "dns_dispatch_createudp (v4)"); } diff --git a/bin/tests/system/pipelined/pipequeries.c b/bin/tests/system/pipelined/pipequeries.c index 0adf5036ff..6466771ff2 100644 --- a/bin/tests/system/pipelined/pipequeries.c +++ b/bin/tests/system/pipelined/pipequeries.c @@ -70,7 +70,7 @@ static void recvresponse(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = (dns_requestevent_t *)event; isc_result_t result; - dns_message_t *query, *response; + dns_message_t *query = NULL, *response = NULL; isc_buffer_t outbuf; char output[1024]; @@ -86,7 +86,6 @@ recvresponse(isc_task_t *task, isc_event_t *event) { query = reqev->ev_arg; - response = NULL; dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); result = dns_request_getresponse(reqev->request, response, @@ -207,7 +206,6 @@ main(int argc, char *argv[]) { isc_timermgr_t *timermgr = NULL; isc_socketmgr_t *socketmgr = NULL; dns_dispatchmgr_t *dispatchmgr = NULL; - unsigned int attrs; dns_dispatch_t *dispatchv4 = NULL; dns_view_t *view = NULL; uint16_t port = PORT; @@ -275,10 +273,9 @@ main(int argc, char *argv[]) { RUNCHECK(isc_task_create(taskmgr, 0, &task)); RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); - attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4; RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - have_src ? &srcaddr : &bind_any, 4, 2, - 3, 5, attrs, &dispatchv4)); + have_src ? &srcaddr : &bind_any, 0, + &dispatchv4)); RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, dispatchmgr, dispatchv4, NULL, &requestmgr)); diff --git a/bin/tests/system/tkey/keycreate.c b/bin/tests/system/tkey/keycreate.c index b5ca6fdb48..6904c1998a 100644 --- a/bin/tests/system/tkey/keycreate.c +++ b/bin/tests/system/tkey/keycreate.c @@ -56,20 +56,20 @@ static char *ip_address = NULL; static int port = 0; -static dst_key_t *ourkey; -static isc_mem_t *mctx; -static dns_tsigkey_t *tsigkey, *initialkey; -static dns_tsig_keyring_t *ring; +static dst_key_t *ourkey = NULL; +static isc_mem_t *mctx = NULL; +static dns_tsigkey_t *tsigkey = NULL, *initialkey = NULL; +static dns_tsig_keyring_t *ring = NULL; static unsigned char noncedata[16]; static isc_buffer_t nonce; -static dns_requestmgr_t *requestmgr; +static dns_requestmgr_t *requestmgr = NULL; static const char *ownername_str = "."; static void recvquery(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = (dns_requestevent_t *)event; isc_result_t result; - dns_message_t *query, *response; + dns_message_t *query = NULL, *response = NULL; char keyname[256]; isc_buffer_t keynamebuf; int type; @@ -134,8 +134,8 @@ sendquery(isc_task_t *task, isc_event_t *event) { dns_fixedname_t ownername; isc_buffer_t namestr, keybuf; unsigned char keydata[9]; - dns_message_t *query; - dns_request_t *request; + dns_message_t *query = NULL; + dns_request_t *request = NULL; static char keystr[] = "0123456789ab"; isc_event_free(&event); @@ -166,14 +166,12 @@ sendquery(isc_task_t *task, isc_event_t *event) { isc_buffer_usedregion(&keybuf, &r); - initialkey = NULL; result = dns_tsigkey_create( dns_fixedname_name(&keyname), DNS_TSIG_HMACMD5_NAME, isc_buffer_base(&keybuf), isc_buffer_usedlength(&keybuf), false, NULL, 0, 0, mctx, ring, &initialkey); CHECK("dns_tsigkey_create", result); - query = NULL; dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query); result = dns_tkey_builddhquery(query, ourkey, @@ -181,7 +179,6 @@ sendquery(isc_task_t *task, isc_event_t *event) { DNS_TSIG_HMACMD5_NAME, &nonce, 3600); CHECK("dns_tkey_builddhquery", result); - request = NULL; result = dns_request_create(requestmgr, query, &address, DNS_REQUESTOPT_TCP, initialkey, TIMEOUT, task, recvquery, query, &request); @@ -196,7 +193,6 @@ main(int argc, char *argv[]) { isc_timermgr_t *timermgr = NULL; isc_socketmgr_t *socketmgr = NULL; isc_socket_t *sock = NULL; - unsigned int attrs; isc_sockaddr_t bind_any; dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatch_t *dispatchv4 = NULL; @@ -224,12 +220,9 @@ main(int argc, char *argv[]) { dns_result_register(); - mctx = NULL; isc_mem_debugging = ISC_MEM_DEBUGRECORD; isc_mem_create(&mctx); - log = NULL; - logconfig = NULL; isc_log_create(mctx, &log, &logconfig); RUNCHECK(dst_lib_init(mctx, NULL)); @@ -241,32 +234,24 @@ main(int argc, char *argv[]) { RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); isc_sockaddr_any(&bind_any); - attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4; RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - &bind_any, 4, 2, 3, 5, attrs, - &dispatchv4)); - requestmgr = NULL; + &bind_any, 0, &dispatchv4)); RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, dispatchmgr, dispatchv4, NULL, &requestmgr)); - ring = NULL; RUNCHECK(dns_tsigkeyring_create(mctx, &ring)); - tctx = NULL; RUNCHECK(dns_tkeyctx_create(mctx, &tctx)); - view = NULL; RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); dns_view_setkeyring(view, ring); dns_tsigkeyring_detach(&ring); - sock = NULL; RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &sock)); RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL)); - ourkey = NULL; type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY; result = dst_key_fromnamedfile(ourkeyname, NULL, type, mctx, &ourkey); CHECK("dst_key_fromnamedfile", result); diff --git a/bin/tests/system/tkey/keydelete.c b/bin/tests/system/tkey/keydelete.c index d4caf2940d..1b8d3dc336 100644 --- a/bin/tests/system/tkey/keydelete.c +++ b/bin/tests/system/tkey/keydelete.c @@ -53,18 +53,18 @@ #define TIMEOUT 30 -static char *ip_address; +static char *ip_address = NULL; static int port; -static isc_mem_t *mctx; -static dns_tsigkey_t *tsigkey; -static dns_tsig_keyring_t *ring; -static dns_requestmgr_t *requestmgr; +static isc_mem_t *mctx = NULL; +static dns_tsigkey_t *tsigkey = NULL; +static dns_tsig_keyring_t *ring = NULL; +static dns_requestmgr_t *requestmgr = NULL; static void recvquery(isc_task_t *task, isc_event_t *event) { dns_requestevent_t *reqev = (dns_requestevent_t *)event; isc_result_t result; - dns_message_t *query, *response; + dns_message_t *query = NULL, *response = NULL; UNUSED(task); @@ -78,7 +78,6 @@ recvquery(isc_task_t *task, isc_event_t *event) { query = reqev->ev_arg; - response = NULL; dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response); result = dns_request_getresponse(reqev->request, response, @@ -108,8 +107,8 @@ sendquery(isc_task_t *task, isc_event_t *event) { struct in_addr inaddr; isc_sockaddr_t address; isc_result_t result; - dns_message_t *query; - dns_request_t *request; + dns_message_t *query = NULL; + dns_request_t *request = NULL; isc_event_free(&event); @@ -119,13 +118,11 @@ sendquery(isc_task_t *task, isc_event_t *event) { } isc_sockaddr_fromin(&address, &inaddr, port); - query = NULL; dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query); result = dns_tkey_builddeletequery(query, tsigkey); CHECK("dns_tkey_builddeletequery", result); - request = NULL; result = dns_request_create(requestmgr, query, &address, DNS_REQUESTOPT_TCP, tsigkey, TIMEOUT, task, recvquery, query, &request); @@ -140,7 +137,6 @@ main(int argc, char **argv) { isc_timermgr_t *timermgr = NULL; isc_socketmgr_t *socketmgr = NULL; isc_socket_t *sock = NULL; - unsigned int attrs; isc_sockaddr_t bind_any; dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatch_t *dispatchv4 = NULL; @@ -169,11 +165,8 @@ main(int argc, char **argv) { dns_result_register(); - mctx = NULL; isc_mem_create(&mctx); - log = NULL; - logconfig = NULL; isc_log_create(mctx, &log, &logconfig); RUNCHECK(dst_lib_init(mctx, NULL)); @@ -184,31 +177,23 @@ main(int argc, char **argv) { RUNCHECK(isc_task_create(taskmgr, 0, &task)); RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); isc_sockaddr_any(&bind_any); - attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_IPV4; RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - &bind_any, 4, 2, 3, 5, attrs, - &dispatchv4)); - requestmgr = NULL; + &bind_any, 0, &dispatchv4)); RUNCHECK(dns_requestmgr_create(mctx, timermgr, socketmgr, taskmgr, dispatchmgr, dispatchv4, NULL, &requestmgr)); - ring = NULL; RUNCHECK(dns_tsigkeyring_create(mctx, &ring)); - tctx = NULL; RUNCHECK(dns_tkeyctx_create(mctx, &tctx)); - view = NULL; RUNCHECK(dns_view_create(mctx, 0, "_test", &view)); dns_view_setkeyring(view, ring); - sock = NULL; RUNCHECK(isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &sock)); RUNCHECK(isc_app_onrun(mctx, task, sendquery, NULL)); - dstkey = NULL; type = DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_KEY; result = dst_key_fromnamedfile(keyname, NULL, type, mctx, &dstkey); CHECK("dst_key_fromnamedfile", result); diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c index 4578fd9472..9c58a337cd 100644 --- a/bin/tools/mdig.c +++ b/bin/tools/mdig.c @@ -2073,7 +2073,7 @@ main(int argc, char *argv[]) { dns_dispatchmgr_t *dispatchmgr = NULL; dns_dispatch_t *dispatchvx = NULL; dns_view_t *view = NULL; - unsigned int attrs, i; + unsigned int i; int ns; RUNCHECK(isc_app_start()); @@ -2128,17 +2128,14 @@ main(int argc, char *argv[]) { RUNCHECK(isc_task_create(taskmgr, 0, &task)); RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr)); - attrs = DNS_DISPATCHATTR_UDP; if (have_ipv4) { isc_sockaddr_any(&bind_any); - attrs |= DNS_DISPATCHATTR_IPV4; } else { isc_sockaddr_any6(&bind_any); - attrs |= DNS_DISPATCHATTR_IPV6; } RUNCHECK(dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - have_src ? &srcaddr : &bind_any, 100, - 100, 17, 19, attrs, &dispatchvx)); + have_src ? &srcaddr : &bind_any, 0, + &dispatchvx)); RUNCHECK(dns_requestmgr_create( mctx, timermgr, socketmgr, taskmgr, dispatchmgr, diff --git a/lib/dns/client.c b/lib/dns/client.c index 3547d3cc81..1d113972b8 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -203,40 +203,18 @@ cleanup: static isc_result_t getudpdispatch(int family, dns_dispatchmgr_t *dispatchmgr, isc_socketmgr_t *socketmgr, isc_taskmgr_t *taskmgr, - bool is_shared, dns_dispatch_t **dispp, - const isc_sockaddr_t *localaddr) { - unsigned int attrs; + dns_dispatch_t **dispp, const isc_sockaddr_t *localaddr) { dns_dispatch_t *disp = NULL; - unsigned maxbuffers, maxrequests, buckets, increment; isc_result_t result; isc_sockaddr_t anyaddr; - attrs = DNS_DISPATCHATTR_UDP; - switch (family) { - case AF_INET: - attrs |= DNS_DISPATCHATTR_IPV4; - break; - case AF_INET6: - attrs |= DNS_DISPATCHATTR_IPV6; - break; - default: - INSIST(0); - ISC_UNREACHABLE(); - } - if (localaddr == NULL) { isc_sockaddr_anyofpf(&anyaddr, family); localaddr = &anyaddr; } - maxbuffers = is_shared ? 1000 : 8; - maxrequests = 32768; - buckets = is_shared ? 16411 : 3; - increment = is_shared ? 16433 : 5; - result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, - localaddr, maxbuffers, maxrequests, - buckets, increment, attrs, &disp); + localaddr, 0, &disp); if (result == ISC_R_SUCCESS) { *dispp = disp; } @@ -334,7 +312,7 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, client->dispatchv4 = NULL; if (localaddr4 != NULL || localaddr6 == NULL) { result = getudpdispatch(AF_INET, dispatchmgr, socketmgr, - taskmgr, true, &dispatchv4, localaddr4); + taskmgr, &dispatchv4, localaddr4); if (result == ISC_R_SUCCESS) { client->dispatchv4 = dispatchv4; } @@ -343,7 +321,7 @@ dns_client_create(isc_mem_t *mctx, isc_appctx_t *actx, isc_taskmgr_t *taskmgr, client->dispatchv6 = NULL; if (localaddr6 != NULL || localaddr4 == NULL) { result = getudpdispatch(AF_INET6, dispatchmgr, socketmgr, - taskmgr, true, &dispatchv6, localaddr6); + taskmgr, &dispatchv6, localaddr6); if (result == ISC_R_SUCCESS) { client->dispatchv6 = dispatchv6; } diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 5a3bbad899..cbb84220ee 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -43,9 +43,6 @@ typedef ISC_LIST(dns_dispentry_t) dns_displist_t; typedef struct dispsocket dispsocket_t; typedef ISC_LIST(dispsocket_t) dispsocketlist_t; -typedef struct dispportentry dispportentry_t; -typedef ISC_LIST(dispportentry_t) dispportlist_t; - typedef struct dns_qid { unsigned int magic; unsigned int qid_nbuckets; /*%< hash table size */ @@ -72,7 +69,6 @@ struct dns_dispatchmgr { isc_mutex_t buffer_lock; unsigned int buffers; /*%< allocated buffers */ unsigned int buffersize; /*%< size of each buffer */ - unsigned int maxbuffers; /*%< max buffers */ isc_refcount_t irefs; @@ -101,8 +97,6 @@ struct dns_dispatchmgr { #define MGR_SHUTTINGDOWN 0x00000001U #define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0) -#define IS_PRIVATE(d) (((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0) - struct dns_dispentry { unsigned int magic; dns_dispatch_t *disp; @@ -119,27 +113,6 @@ struct dns_dispentry { ISC_LINK(dns_dispentry_t) link; }; -/*% - * Maximum number of dispatch sockets that can be pooled for reuse. The - * appropriate value may vary, but experiments have shown a busy caching server - * may need more than 1000 sockets concurrently opened. The maximum allowable - * number of dispatch sockets (per manager) will be set to the double of this - * value. - */ -#ifndef DNS_DISPATCH_POOLSOCKS -#define DNS_DISPATCH_POOLSOCKS 2048 -#endif /* ifndef DNS_DISPATCH_POOLSOCKS */ - -/*% - * Quota to control the number of dispatch sockets. If a dispatch has more - * than the quota of sockets, new queries will purge oldest ones, so that - * a massive number of outstanding queries won't prevent subsequent queries - * (especially if the older ones take longer time and result in timeout). - */ -#ifndef DNS_DISPATCH_SOCKSQUOTA -#define DNS_DISPATCH_SOCKSQUOTA 3072 -#endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */ - /*% * Fixed UDP buffer size. */ @@ -152,31 +125,14 @@ struct dispsocket { isc_socket_t *socket; dns_dispatch_t *disp; isc_sockaddr_t host; - dispportentry_t *portentry; dns_dispentry_t *resp; isc_task_t *task; + in_port_t port; ISC_LINK(dispsocket_t) link; unsigned int bucket; ISC_LINK(dispsocket_t) blink; }; -/*% - * A port table entry. We remember every port we first open in a table with a - * reference counter so that we can 'reuse' the same port (with different - * destination addresses) using the SO_REUSEADDR socket option. - */ -struct dispportentry { - in_port_t port; - isc_refcount_t refs; - ISC_LINK(struct dispportentry) link; -}; - -#ifndef DNS_DISPATCH_PORTTABLESIZE -#define DNS_DISPATCH_PORTTABLESIZE 1024 -#endif /* ifndef DNS_DISPATCH_PORTTABLESIZE */ - -#define INVALID_BUCKET (0xffffdead) - /*% * Number of tasks for each dispatch that use separate sockets for different * transactions. This must be a power of 2 as it will divide 32 bit numbers @@ -195,11 +151,10 @@ struct dns_dispatch { * 1st task (task[0]) for internal control events. */ isc_task_t *task[MAX_INTERNAL_TASKS]; - isc_socket_t *socket; /*%< isc socket attached to */ - isc_sockaddr_t local; /*%< local address */ - in_port_t localport; /*%< local UDP port */ - isc_sockaddr_t peer; /*%< peer address (TCP) */ - unsigned int maxrequests; /*%< max requests */ + isc_socket_t *socket; /*%< isc socket attached to */ + isc_sockaddr_t local; /*%< local address */ + in_port_t localport; /*%< local UDP port */ + isc_sockaddr_t peer; /*%< peer address (TCP) */ isc_event_t *ctlevent; isc_mem_t *sepool; /*%< pool for socket events */ @@ -214,8 +169,7 @@ struct dns_dispatch { isc_refcount_t refcount; dns_dispatchevent_t *failsafe_ev; /*%< failsafe cancel event */ unsigned int shutting_down : 1, shutdown_out : 1, connected : 1, - tcpmsg_valid : 1, recv_pending : 1; /*%< is a recv() pending? * - */ + tcpmsg_valid : 1, recv_pending : 1; isc_result_t shutdown_why; ISC_LIST(dispsocket_t) activesockets; ISC_LIST(dispsocket_t) inactivesockets; @@ -223,8 +177,6 @@ struct dns_dispatch { unsigned int requests; /*%< how many requests we have */ unsigned int tcpbuffers; /*%< allocated buffers */ dns_tcpmsg_t tcpmsg; /*%< for tcp streams */ - dns_qid_t *qid; - dispportlist_t *port_table; /*%< hold ports 'owned' by us */ }; #define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ') @@ -242,23 +194,65 @@ struct dns_dispatch { #define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r') #define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC) -#define DNS_QID(disp) \ - ((disp)->socktype == isc_sockettype_tcp) ? (disp)->qid \ - : (disp)->mgr->qid +/*% + * Maximum number of dispatch sockets that can be pooled for reuse. The + * appropriate value may vary, but experiments have shown a busy caching server + * may need more than 1000 sockets concurrently opened. The maximum allowable + * number of dispatch sockets (per manager) will be set to the double of this + * value. + */ +#ifndef DNS_DISPATCH_POOLSOCKS +#define DNS_DISPATCH_POOLSOCKS 2048 +#endif /* ifndef DNS_DISPATCH_POOLSOCKS */ /*% - * Locking a query port buffer is a bit tricky. We access the buffer without - * locking until qid is created. Technically, there is a possibility of race - * between the creation of qid and access to the port buffer; in practice, - * however, this should be safe because qid isn't created until the first - * dispatch is created and there should be no contending situation until then. + * Quota to control the number of UDP dispatch sockets. If a dispatch has + * more than the quota of sockets, new queries will purge oldest ones, so + * that a massive number of outstanding queries won't prevent subsequent + * queries (especially if the older ones take longer time and result in + * timeout). */ -#define PORTBUFLOCK(mgr) \ - if ((mgr)->qid != NULL) \ - LOCK(&((mgr)->qid->lock)) -#define PORTBUFUNLOCK(mgr) \ - if ((mgr)->qid != NULL) \ - UNLOCK((&(mgr)->qid->lock)) +#ifndef DNS_DISPATCH_SOCKSQUOTA +#define DNS_DISPATCH_SOCKSQUOTA 3072 +#endif /* ifndef DNS_DISPATCH_SOCKSQUOTA */ + +/*% + * Number of buffers available for all dispatches in the buffery memory + * pool. + */ +#ifndef DNS_DISPATCH_MAXBUFFERS +#define DNS_DISPATCH_MAXBUFFERS 32768 +#endif /* ifndef DNS_DISPATCH_MAXBUFFERS */ + +/*% + * Number of dispatch sockets available for all dispatches in the + * socket memory pool. + */ +#ifndef DNS_DISPATCH_MAXSOCKETS +#define DNS_DISPATCH_MAXSOCKETS 32768 +#endif /* ifndef DNS_DISPATCH_MAXSOCKETS */ + +/*% + * Quota to control the number of concurrent requests that can be handled + * by each TCP dispatch. (UDP dispatches do not currently support socket + * sharing.) + */ +#ifndef DNS_DISPATCH_MAXREQUESTS +#define DNS_DISPATCH_MAXREQUESTS 32768 +#endif /* ifndef DNS_DISPATCH_MAXREQUESTS */ + +/*% + * Number of buckets in the QID hash table, and the value to + * increment the QID by when attempting to avoid collisions. + * The number of buckets should be prime, and the increment + * should be the next higher prime number. + */ +#ifndef DNS_QID_BUCKETS +#define DNS_QID_BUCKETS 16411 +#endif /* ifndef DNS_QID_BUCKETS */ +#ifndef DNS_QID_INCREMENT +#define DNS_QID_INCREMENT 16433 +#endif /* ifndef DNS_QID_INCREMENT */ /* * Statics. @@ -301,21 +295,18 @@ dispatch_free(dns_dispatch_t **dispp); static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - unsigned int maxrequests, unsigned int attributes, - dns_dispatch_t **dispp); + unsigned int attributes, dns_dispatch_t **dispp); static bool destroy_mgr_ok(dns_dispatchmgr_t *mgr); static void destroy_mgr(dns_dispatchmgr_t **mgrp); -static isc_result_t -qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, - unsigned int increment, dns_qid_t **qidp, bool needaddrtable); +static void +qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp); static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp); static isc_result_t open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local, - unsigned int options, isc_socket_t **sockp, - isc_socket_t *dup_socket); + unsigned int options, isc_socket_t **sockp); #define LVL(x) ISC_LOG_DEBUG(x) @@ -433,9 +424,7 @@ dns_hash(dns_qid_t *qid, const isc_sockaddr_t *dest, dns_messageid_t id, static dns_dispentry_t * linear_first(dns_qid_t *qid) { dns_dispentry_t *ret = NULL; - unsigned int bucket; - - bucket = 0; + unsigned int bucket = 0; while (bucket < qid->qid_nbuckets) { ret = ISC_LIST_HEAD(qid->qid_table[bucket]); @@ -462,8 +451,7 @@ linear_next(dns_qid_t *qid, dns_dispentry_t *resp) { return (ret); } - bucket = resp->bucket; - bucket++; + bucket = resp->bucket + 1; while (bucket < qid->qid_nbuckets) { ret = ISC_LIST_HEAD(qid->qid_table[bucket]); if (ret != NULL) { @@ -551,67 +539,6 @@ destroy_disp(isc_task_t *task, isc_event_t *event) { } } -/*% - * Manipulate port table per dispatch: find an entry for a given port number, - * create a new entry, and decrement a given entry with possible clean-up. - */ -static dispportentry_t * -port_search(dns_dispatch_t *disp, in_port_t port) { - dispportentry_t *portentry = NULL; - - REQUIRE(disp->port_table != NULL); - - portentry = ISC_LIST_HEAD( - disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE]); - while (portentry != NULL) { - if (portentry->port == port) { - return (portentry); - } - portentry = ISC_LIST_NEXT(portentry, link); - } - - return (NULL); -} - -static dispportentry_t * -new_portentry(dns_dispatch_t *disp, in_port_t port) { - dispportentry_t *portentry = NULL; - dns_qid_t *qid = NULL; - - REQUIRE(disp->port_table != NULL); - - portentry = isc_mem_get(disp->mgr->mctx, sizeof(*portentry)); - portentry->port = port; - isc_refcount_init(&portentry->refs, 1); - ISC_LINK_INIT(portentry, link); - qid = DNS_QID(disp); - LOCK(&qid->lock); - ISC_LIST_APPEND(disp->port_table[port % DNS_DISPATCH_PORTTABLESIZE], - portentry, link); - UNLOCK(&qid->lock); - - return (portentry); -} - -/*% - * The caller must hold the qid->lock. - */ -static void -deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { - dispportentry_t *portentry = *portentryp; - *portentryp = NULL; - - REQUIRE(disp->port_table != NULL); - REQUIRE(portentry != NULL); - - if (isc_refcount_decrement(&portentry->refs) == 1) { - ISC_LIST_UNLINK(disp->port_table[portentry->port % - DNS_DISPATCH_PORTTABLESIZE], - portentry, link); - isc_mem_put(disp->mgr->mctx, portentry, sizeof(*portentry)); - } -} - /*% * Find a dispsocket for socket address 'dest', and port number 'port'. * Return NULL if no such entry exists. Requires qid->lock to be held. @@ -627,10 +554,8 @@ socket_search(dns_qid_t *qid, const isc_sockaddr_t *dest, in_port_t port, dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]); while (dispsock != NULL) { - if (dispsock->portentry != NULL && - dispsock->portentry->port == port && - isc_sockaddr_equal(dest, &dispsock->host)) - { + if (dispsock->port == port && + isc_sockaddr_equal(dest, &dispsock->host)) { return (dispsock); } dispsock = ISC_LIST_NEXT(dispsock, blink); @@ -649,6 +574,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, in_port_t *portp) { int i; dns_dispatchmgr_t *mgr = disp->mgr; + dns_qid_t *qid = mgr->qid; isc_socket_t *sock = NULL; isc_result_t result = ISC_R_FAILURE; in_port_t port; @@ -657,9 +583,6 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, dispsocket_t *dispsock = NULL; unsigned int nports; in_port_t *ports = NULL; - isc_socket_options_t bindoptions; - dispportentry_t *portentry = NULL; - dns_qid_t *qid = NULL; if (isc_sockaddr_pf(&disp->local) == AF_INET) { nports = mgr->nv4ports; @@ -696,7 +619,6 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, * very likely to fail in bind(2) or connect(2). */ localaddr = disp->local; - qid = DNS_QID(disp); for (i = 0; i < 64; i++) { port = ports[isc_random_uniform(nports)]; @@ -709,20 +631,9 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, continue; } UNLOCK(&qid->lock); - bindoptions = 0; - portentry = port_search(disp, port); - - if (portentry != NULL) { - bindoptions |= ISC_SOCKET_REUSEADDRESS; - } - result = open_socket(sockmgr, &localaddr, bindoptions, &sock, - NULL); + result = open_socket(sockmgr, &localaddr, + ISC_SOCKET_REUSEADDRESS, &sock); if (result == ISC_R_SUCCESS) { - if (portentry == NULL) { - portentry = new_portentry(disp, port); - } else { - isc_refcount_increment(&portentry->refs); - } break; } else if (result == ISC_R_NOPERM) { char buf[ISC_SOCKADDR_FORMATSIZE]; @@ -746,8 +657,9 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, dispsock->socket = sock; dispsock->host = *dest; dispsock->bucket = bucket; + dispsock->port = port; + LOCK(&qid->lock); - dispsock->portentry = portentry; ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink); UNLOCK(&qid->lock); *dispsockp = dispsock; @@ -762,7 +674,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest, static void destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { dispsocket_t *dispsock = NULL; - dns_qid_t *qid = DNS_QID(disp); + dns_qid_t *qid = disp->mgr->qid; /* * The dispatch must be locked. @@ -775,11 +687,6 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { disp->nsockets--; dispsock->magic = 0; - if (dispsock->portentry != NULL) { - LOCK(&qid->lock); - deref_portentry(disp, &dispsock->portentry); - UNLOCK(&qid->lock); - } if (dispsock->socket != NULL) { isc_socket_detach(&dispsock->socket); } @@ -802,7 +709,7 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) { static void deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { isc_result_t result; - dns_qid_t *qid = DNS_QID(disp); + dns_qid_t *qid = disp->mgr->qid; /* * The dispatch must be locked. @@ -813,12 +720,6 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) { dispsock->resp->dispsocket = NULL; } - INSIST(dispsock->portentry != NULL); - - LOCK(&qid->lock); - deref_portentry(disp, &dispsock->portentry); - UNLOCK(&qid->lock); - if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) { destroy_dispsocket(disp, &dispsock); } else { @@ -896,7 +797,7 @@ free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) { static void * allocate_udp_buffer(dns_dispatch_t *disp) { LOCK(&disp->mgr->buffer_lock); - if (disp->mgr->buffers >= disp->mgr->maxbuffers) { + if (disp->mgr->buffers >= DNS_DISPATCH_MAXBUFFERS) { UNLOCK(&disp->mgr->buffer_lock); return (NULL); } @@ -1238,7 +1139,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { REQUIRE(VALID_DISPATCH(disp)); - qid = disp->qid; + qid = disp->mgr->qid; LOCK(&disp->lock); @@ -1512,8 +1413,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) { static isc_result_t open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local, - unsigned int options, isc_socket_t **sockp, - isc_socket_t *dup_socket) { + unsigned int options, isc_socket_t **sockp) { isc_socket_t *sock = NULL; isc_result_t result; @@ -1523,15 +1423,6 @@ open_socket(isc_socketmgr_t *mgr, const isc_sockaddr_t *local, if (result != ISC_R_SUCCESS) { return (result); } - } else if (dup_socket != NULL && !isc_socket_hasreuseport()) { - result = isc_socket_dup(dup_socket, &sock); - if (result != ISC_R_SUCCESS) { - return (result); - } - - isc_socket_setname(sock, "dispatcher", NULL); - *sockp = sock; - return (ISC_R_SUCCESS); } else { result = isc_socket_create(mgr, isc_sockaddr_pf(local), isc_sockettype_udp, &sock); @@ -1601,7 +1492,6 @@ setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset, } while (p++ < 65535); INSIST(i4 == nv4ports && i6 == nv6ports); - PORTBUFLOCK(mgr); if (mgr->v4ports != NULL) { isc_mem_put(mgr->mctx, mgr->v4ports, mgr->nv4ports * sizeof(in_port_t)); @@ -1615,7 +1505,6 @@ setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset, } mgr->v6ports = v6ports; mgr->nv6ports = nv6ports; - PORTBUFUNLOCK(mgr); return (ISC_R_SUCCESS); } @@ -1634,7 +1523,7 @@ dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) { REQUIRE(mgrp != NULL && *mgrp == NULL); mgr = isc_mem_get(mctx, sizeof(dns_dispatchmgr_t)); - *mgr = (dns_dispatchmgr_t){ .maxbuffers = 20000 }; + *mgr = (dns_dispatchmgr_t){ 0 }; isc_mem_attach(mctx, &mgr->mctx); @@ -1653,6 +1542,7 @@ dns_dispatchmgr_create(isc_mem_t *mctx, dns_dispatchmgr_t **mgrp) { isc_portset_destroy(mctx, &v4portset); isc_portset_destroy(mctx, &v6portset); + qid_allocate(mgr, &mgr->qid); mgr->magic = DNS_DISPATCHMGR_MAGIC; *mgrp = mgr; @@ -1681,60 +1571,6 @@ dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset, return (setavailports(mgr, v4portset, v6portset)); } -static isc_result_t -dispatchmgr_setudp(dns_dispatchmgr_t *mgr, unsigned int maxbuffers, - unsigned int maxrequests, unsigned int buckets, - unsigned int increment) { - isc_result_t result; - - REQUIRE(VALID_DISPATCHMGR(mgr)); - REQUIRE(maxbuffers > 0); - REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */ - REQUIRE(increment > buckets); - UNUSED(maxrequests); - - /* - * Keep some number of items around. This should be a config - * option. For now, keep 8, but later keep at least two even - * if the caller wants less. This allows us to ensure certain - * things, like an event can be "freed" and the next allocation - * will always succeed. - * - * Note that if limits are placed on anything here, we use one - * event internally, so the actual limit should be "wanted + 1." - * - * XXXMLG - */ - - if (maxbuffers < 8) { - maxbuffers = 8; - } - - /* Adjust buffer pool if needed - * - * We only increase maxbuffers to avoid accidental buffer - * shortage. Ideally we'd separate the manager-wide maximum - * from per-dispatch limits and respect the latter within the - * global limit. But at this moment that's deemed to be - * overkilling and isn't worth additional implementation - * complexity. - */ - LOCK(&mgr->buffer_lock); - if (maxbuffers > mgr->maxbuffers) { - mgr->maxbuffers = maxbuffers; - } - UNLOCK(&mgr->buffer_lock); - - if (mgr->qid == NULL) { - result = qid_allocate(mgr, buckets, increment, &mgr->qid, true); - if (result != ISC_R_SUCCESS) { - return (result); - } - } - - return (ISC_R_SUCCESS); -} - void dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) { dns_dispatchmgr_t *mgr = NULL; @@ -1767,42 +1603,31 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats) { isc_stats_attach(stats, &mgr->stats); } -static isc_result_t -qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets, - unsigned int increment, dns_qid_t **qidp, bool needsocktable) { +static void +qid_allocate(dns_dispatchmgr_t *mgr, dns_qid_t **qidp) { dns_qid_t *qid = NULL; unsigned int i; - REQUIRE(VALID_DISPATCHMGR(mgr)); - REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */ - REQUIRE(increment > buckets); REQUIRE(qidp != NULL && *qidp == NULL); qid = isc_mem_get(mgr->mctx, sizeof(*qid)); + *qid = (dns_qid_t){ .qid_nbuckets = DNS_QID_BUCKETS, + .qid_increment = DNS_QID_INCREMENT }; qid->qid_table = isc_mem_get(mgr->mctx, - buckets * sizeof(dns_displist_t)); - - qid->sock_table = NULL; - if (needsocktable) { - qid->sock_table = isc_mem_get( - mgr->mctx, buckets * sizeof(dispsocketlist_t)); - } + DNS_QID_BUCKETS * sizeof(dns_displist_t)); + qid->sock_table = isc_mem_get( + mgr->mctx, DNS_QID_BUCKETS * sizeof(dispsocketlist_t)); isc_mutex_init(&qid->lock); - for (i = 0; i < buckets; i++) { + for (i = 0; i < qid->qid_nbuckets; i++) { ISC_LIST_INIT(qid->qid_table[i]); - if (qid->sock_table != NULL) { - ISC_LIST_INIT(qid->sock_table[i]); - } + ISC_LIST_INIT(qid->sock_table[i]); } - qid->qid_nbuckets = buckets; - qid->qid_increment = increment; qid->magic = QID_MAGIC; *qidp = qid; - return (ISC_R_SUCCESS); } static void @@ -1818,10 +1643,8 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) { qid->magic = 0; isc_mem_put(mctx, qid->qid_table, qid->qid_nbuckets * sizeof(dns_displist_t)); - if (qid->sock_table != NULL) { - isc_mem_put(mctx, qid->sock_table, - qid->qid_nbuckets * sizeof(dispsocketlist_t)); - } + isc_mem_put(mctx, qid->sock_table, + qid->qid_nbuckets * sizeof(dispsocketlist_t)); isc_mutex_destroy(&qid->lock); isc_mem_put(mctx, qid, sizeof(*qid)); } @@ -1830,8 +1653,7 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) { * Allocate and set important limits. */ static isc_result_t -dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, - dns_dispatch_t **dispp) { +dispatch_allocate(dns_dispatchmgr_t *mgr, dns_dispatch_t **dispp) { dns_dispatch_t *disp = NULL; REQUIRE(VALID_DISPATCHMGR(mgr)); @@ -1846,7 +1668,6 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests, isc_refcount_increment0(&mgr->irefs); *disp = (dns_dispatch_t){ .mgr = mgr, - .maxrequests = maxrequests, .shutdown_why = ISC_R_UNEXPECTED }; isc_refcount_init(&disp->refcount, 1); ISC_LINK_INIT(disp, link); @@ -1891,19 +1712,6 @@ dispatch_free(dns_dispatch_t **dispp) { isc_mem_put(mgr->mctx, disp->failsafe_ev, sizeof(*disp->failsafe_ev)); disp->failsafe_ev = NULL; - if (disp->qid != NULL) { - qid_destroy(mgr->mctx, &disp->qid); - } - - if (disp->port_table != NULL) { - for (int i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) { - INSIST(ISC_LIST_EMPTY(disp->port_table[i])); - } - isc_mem_put(mgr->mctx, disp->port_table, - sizeof(disp->port_table[0]) * - DNS_DISPATCH_PORTTABLESIZE); - } - disp->mgr = NULL; isc_mutex_destroy(&disp->lock); disp->magic = 0; @@ -1914,52 +1722,34 @@ dispatch_free(dns_dispatch_t **dispp) { isc_result_t dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - const isc_sockaddr_t *destaddr, unsigned int buffersize, - unsigned int maxbuffers, unsigned int maxrequests, - unsigned int buckets, unsigned int increment, - unsigned int attributes, dns_dispatch_t **dispp) { + const isc_sockaddr_t *destaddr, unsigned int attributes, + dns_dispatch_t **dispp) { isc_result_t result; dns_dispatch_t *disp = NULL; - - UNUSED(maxbuffers); - UNUSED(buffersize); + int pf; REQUIRE(VALID_DISPATCHMGR(mgr)); REQUIRE(isc_socket_gettype(sock) == isc_sockettype_tcp); - REQUIRE((attributes & DNS_DISPATCHATTR_TCP) != 0); - REQUIRE((attributes & DNS_DISPATCHATTR_UDP) == 0); - if (destaddr == NULL) { - attributes |= DNS_DISPATCHATTR_PRIVATE; /* XXXMLG */ - } + attributes |= DNS_DISPATCHATTR_TCP; + attributes &= ~DNS_DISPATCHATTR_UDP; LOCK(&mgr->lock); - /* - * dispatch_allocate() checks mgr for us. - * qid_allocate() checks buckets and increment for us. - */ - disp = NULL; - result = dispatch_allocate(mgr, maxrequests, &disp); + result = dispatch_allocate(mgr, &disp); if (result != ISC_R_SUCCESS) { UNLOCK(&mgr->lock); return (result); } - result = qid_allocate(mgr, buckets, increment, &disp->qid, false); - if (result != ISC_R_SUCCESS) { - goto deallocate_dispatch; - } - disp->socktype = isc_sockettype_tcp; - disp->socket = NULL; isc_socket_attach(sock, &disp->socket); disp->ntasks = 1; disp->task[0] = NULL; result = isc_task_create(taskmgr, 50, &disp->task[0]); if (result != ISC_R_SUCCESS) { - goto kill_socket; + goto cleanup; } disp->ctlevent = @@ -1971,17 +1761,18 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg); disp->tcpmsg_valid = 1; - disp->attributes = attributes; - if (destaddr == NULL) { (void)isc_socket_getpeername(sock, &disp->peer); + attributes |= DNS_DISPATCHATTR_PRIVATE; } else { disp->peer = *destaddr; } + pf = isc_sockaddr_pf(&disp->peer); + if (localaddr == NULL) { if (destaddr != NULL) { - switch (isc_sockaddr_pf(destaddr)) { + switch (pf) { case AF_INET: isc_sockaddr_any(&disp->local); break; @@ -1996,6 +1787,22 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, disp->local = *localaddr; } + switch (pf) { + case PF_INET: + attributes |= DNS_DISPATCHATTR_IPV4; + break; + + case PF_INET6: + attributes |= DNS_DISPATCHATTR_IPV6; + break; + + default: + result = ISC_R_NOTIMPLEMENTED; + goto cleanup; + } + + disp->attributes = attributes; + /* * Append it to the dispatcher list. */ @@ -2012,9 +1819,8 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, return (ISC_R_SUCCESS); -kill_socket: +cleanup: isc_socket_detach(&disp->socket); -deallocate_dispatch: dispatch_free(&disp); UNLOCK(&mgr->lock); @@ -2108,8 +1914,6 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr, isc_result_t dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - unsigned int maxbuffers, unsigned int maxrequests, - unsigned int buckets, unsigned int increment, unsigned int attributes, dns_dispatch_t **dispp) { isc_result_t result; dns_dispatch_t *disp = NULL; @@ -2118,21 +1922,14 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, REQUIRE(sockmgr != NULL); REQUIRE(localaddr != NULL); REQUIRE(taskmgr != NULL); - REQUIRE(maxbuffers > 0); - REQUIRE(buckets < 2097169); /* next prime > 65536 * 32 */ - REQUIRE(increment > buckets); REQUIRE(dispp != NULL && *dispp == NULL); - REQUIRE((attributes & DNS_DISPATCHATTR_TCP) == 0); - result = dispatchmgr_setudp(mgr, maxbuffers, maxrequests, buckets, - increment); - if (result != ISC_R_SUCCESS) { - return (result); - } + attributes |= DNS_DISPATCHATTR_UDP; + attributes &= ~DNS_DISPATCHATTR_TCP; LOCK(&mgr->lock); result = dispatch_createudp(mgr, sockmgr, taskmgr, localaddr, - maxrequests, attributes, &disp); + attributes, &disp); if (result == ISC_R_SUCCESS) { *dispp = disp; @@ -2145,23 +1942,24 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - unsigned int maxrequests, unsigned int attributes, - dns_dispatch_t **dispp) { + unsigned int attributes, dns_dispatch_t **dispp) { isc_result_t result; dns_dispatch_t *disp = NULL; isc_socket_t *sock = NULL; isc_sockaddr_t sa_any; - int i = 0; + int pf, i = 0; /* * dispatch_allocate() checks mgr for us. */ disp = NULL; - result = dispatch_allocate(mgr, maxrequests, &disp); + result = dispatch_allocate(mgr, &disp); if (result != ISC_R_SUCCESS) { return (result); } + pf = isc_sockaddr_pf(localaddr); + disp->socktype = isc_sockettype_udp; /* @@ -2170,9 +1968,9 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, * but we don't keep it open; sockets used for sending requests * will be created later on demand. */ - isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr)); + isc_sockaddr_anyofpf(&sa_any, pf); if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) { - result = open_socket(sockmgr, localaddr, 0, &sock, NULL); + result = open_socket(sockmgr, localaddr, 0, &sock); if (sock != NULL) { isc_socket_detach(&sock); } @@ -2181,13 +1979,6 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, } } - disp->port_table = isc_mem_get(mgr->mctx, - sizeof(disp->port_table[0]) * - DNS_DISPATCH_PORTTABLESIZE); - for (i = 0; i < DNS_DISPATCH_PORTTABLESIZE; i++) { - ISC_LIST_INIT(disp->port_table[i]); - } - if (isc_log_wouldlog(dns_lctx, 90)) { char addrbuf[ISC_SOCKADDR_FORMATSIZE]; @@ -2225,6 +2016,21 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, attributes &= ~DNS_DISPATCHATTR_TCP; attributes |= DNS_DISPATCHATTR_UDP; + + switch (pf) { + case PF_INET: + attributes |= DNS_DISPATCHATTR_IPV4; + break; + + case PF_INET6: + attributes |= DNS_DISPATCHATTR_IPV6; + break; + + default: + result = ISC_R_NOTIMPLEMENTED; + goto kill_socket; + } + disp->attributes = attributes; /* @@ -2330,11 +2136,13 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, return (ISC_R_SHUTTINGDOWN); } - if (disp->requests >= disp->maxrequests) { + if (disp->requests >= DNS_DISPATCH_MAXREQUESTS) { UNLOCK(&disp->lock); return (ISC_R_QUOTA); } + qid = disp->mgr->qid; + if (disp->socktype == isc_sockettype_udp && disp->nsockets > DNS_DISPATCH_SOCKSQUOTA) { @@ -2369,8 +2177,6 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, ISC_LIST_APPEND(disp->activesockets, oldestsocket, link); } - qid = DNS_QID(disp); - if (disp->socktype == isc_sockettype_udp) { /* * Get a separate UDP socket with a random port number. @@ -2440,7 +2246,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, ISC_LIST_APPEND(qid->qid_table[bucket], res, link); UNLOCK(&qid->lock); - inc_stats(disp->mgr, (qid == disp->mgr->qid) + inc_stats(disp->mgr, (disp->socktype == isc_sockettype_udp) ? dns_resstatscounter_disprequdp : dns_resstatscounter_dispreqtcp); @@ -2463,7 +2269,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, unsigned int options, disp->requests--; dec_stats(disp->mgr, - (qid == disp->mgr->qid) + (disp->socktype == isc_sockettype_udp) ? dns_resstatscounter_disprequdp : dns_resstatscounter_dispreqtcp); @@ -2570,8 +2376,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, REQUIRE(VALID_DISPATCH(disp)); mgr = disp->mgr; REQUIRE(VALID_DISPATCHMGR(mgr)); - - qid = DNS_QID(disp); + qid = mgr->qid; if (sockevent != NULL) { REQUIRE(*sockevent != NULL); @@ -2585,7 +2390,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp, INSIST(disp->requests > 0); disp->requests--; - dec_stats(disp->mgr, (qid == disp->mgr->qid) + dec_stats(disp->mgr, (disp->socktype == isc_sockettype_udp) ? dns_resstatscounter_disprequdp : dns_resstatscounter_dispreqtcp); @@ -2677,14 +2482,12 @@ static void do_cancel(dns_dispatch_t *disp) { dns_dispatchevent_t *ev = NULL; dns_dispentry_t *resp = NULL; - dns_qid_t *qid = NULL; + dns_qid_t *qid = disp->mgr->qid; if (disp->shutdown_out == 1) { return; } - qid = DNS_QID(disp); - /* * Search for the first response handler without packets outstanding * unless a specific handler is given. @@ -2827,8 +2630,7 @@ dns_dispatchset_create(isc_mem_t *mctx, isc_socketmgr_t *sockmgr, for (i = 1; i < n; i++) { dset->dispatches[i] = NULL; result = dispatch_createudp(mgr, sockmgr, taskmgr, - &source->local, source->maxrequests, - source->attributes, + &source->local, source->attributes, &dset->dispatches[i]); if (result != ISC_R_SUCCESS) { goto fail; diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index dfae6ff87e..c9bdc42954 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -207,8 +207,6 @@ dns_dispatchmgr_setstats(dns_dispatchmgr_t *mgr, isc_stats_t *stats); isc_result_t dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - unsigned int maxbuffers, unsigned int maxrequests, - unsigned int buckets, unsigned int increment, unsigned int attributes, dns_dispatch_t **dispp); /*%< * Create a new UDP dispatch. @@ -218,16 +216,6 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, * *\li dispp != NULL && *disp == NULL * - *\li 512 <= buffersize <= 64k - * - *\li maxbuffers > 0 - * - *\li buckets < 2097169 - * - *\li increment > buckets - * - *\li (attributes & DNS_DISPATCHATTR_TCP) == 0 - * * Returns: *\li ISC_R_SUCCESS -- success. * @@ -237,25 +225,11 @@ dns_dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_result_t dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, isc_taskmgr_t *taskmgr, const isc_sockaddr_t *localaddr, - const isc_sockaddr_t *destaddr, unsigned int buffersize, - unsigned int maxbuffers, unsigned int maxrequests, - unsigned int buckets, unsigned int increment, - unsigned int attributes, dns_dispatch_t **dispp); + const isc_sockaddr_t *destaddr, unsigned int attributes, + dns_dispatch_t **dispp); /*%< * Create a new dns_dispatch and attach it to the provided isc_socket_t. * - * For all dispatches, "buffersize" is the maximum packet size we will - * accept. - * - * "maxbuffers" and "maxrequests" control the number of buffers in the - * overall system and the number of buffers which can be allocated to - * requests. - * - * "buckets" is the number of buckets to use, and should be prime. - * - * "increment" is used in a collision avoidance function, and needs to be - * a prime > buckets, and not 2. - * * Requires: * *\li mgr is a valid dispatch manager. @@ -264,19 +238,6 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock, * *\li task is a valid task that can be used internally to this dispatcher. * - * \li 512 <= buffersize <= 64k - * - *\li maxbuffers > 0. - * - *\li maxrequests <= maxbuffers. - * - *\li buckets < 2097169 (the next prime after 65536 * 32) - * - *\li increment > buckets (and prime). - * - *\li attributes includes #DNS_DISPATCHATTR_TCP and does not include - * #DNS_DISPATCHATTR_UDP. - * * Returns: *\li ISC_R_SUCCESS -- success. * diff --git a/lib/dns/request.c b/lib/dns/request.c index c9256377d3..fed16798ee 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -119,8 +119,6 @@ static void req_response(isc_task_t *task, isc_event_t *event); static void req_timeout(isc_task_t *task, isc_event_t *event); -static isc_socket_t * -req_getsocket(dns_request_t *request); static void req_connected(isc_task_t *task, isc_event_t *event); static void @@ -423,8 +421,9 @@ req_send(dns_request_t *request, isc_task_t *task, REQUIRE(VALID_REQUEST(request)); - sock = req_getsocket(request); + sock = dns_dispatch_getentrysocket(request->dispentry); isc_buffer_usedregion(request->query, &r); + /* * We could connect the socket when we are using an exclusive dispatch * as we do in resolver.c, but we prefer implementation simplicity @@ -456,29 +455,11 @@ new_request(isc_mem_t *mctx, dns_request_t **requestp) { dns_request_t *request; request = isc_mem_get(mctx, sizeof(*request)); - - /* - * Zero structure. - */ - request->magic = 0; - request->mctx = NULL; - request->flags = 0; + *request = (dns_request_t){ .dscp = -1 }; ISC_LINK_INIT(request, link); - request->query = NULL; - request->answer = NULL; - request->event = NULL; - request->dispatch = NULL; - request->dispentry = NULL; - request->timer = NULL; - request->requestmgr = NULL; - request->tsig = NULL; - request->tsigkey = NULL; - request->dscp = -1; ISC_EVENT_INIT(&request->ctlevent, sizeof(request->ctlevent), 0, NULL, DNS_EVENT_REQUESTCONTROL, do_cancel, request, NULL, NULL, NULL); - request->canceling = false; - request->udpcount = 0; isc_mem_attach(mctx, &request->mctx); @@ -513,14 +494,12 @@ isblackholed(dns_dispatchmgr_t *dispatchmgr, const isc_sockaddr_t *destaddr) { } static isc_result_t -create_tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, - const isc_sockaddr_t *srcaddr, - const isc_sockaddr_t *destaddr, isc_dscp_t dscp, - bool *connected, dns_dispatch_t **dispatchp) { +tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, + const isc_sockaddr_t *srcaddr, const isc_sockaddr_t *destaddr, + isc_dscp_t dscp, bool *connected, dns_dispatch_t **dispatchp) { isc_result_t result; isc_socket_t *sock = NULL; isc_sockaddr_t src; - unsigned int attrs; isc_sockaddr_t bind_any; if (!newtcp) { @@ -556,27 +535,20 @@ create_tcp_dispatch(bool newtcp, dns_requestmgr_t *requestmgr, goto cleanup; } - attrs = DNS_DISPATCHATTR_TCP; - if (isc_sockaddr_pf(destaddr) == AF_INET) { - attrs |= DNS_DISPATCHATTR_IPV4; - } else { - attrs |= DNS_DISPATCHATTR_IPV6; - } - isc_socket_dscp(sock, dscp); - result = dns_dispatch_createtcp( - requestmgr->dispatchmgr, sock, requestmgr->taskmgr, srcaddr, - destaddr, 4096, 32768, 32768, 16411, 16433, attrs, dispatchp); + result = dns_dispatch_createtcp(requestmgr->dispatchmgr, sock, + requestmgr->taskmgr, srcaddr, destaddr, + 0, dispatchp); + cleanup: isc_socket_detach(&sock); return (result); } static isc_result_t -find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, - const isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) { +udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, + const isc_sockaddr_t *destaddr, dns_dispatch_t **dispatchp) { dns_dispatch_t *disp = NULL; - unsigned int attrs; if (srcaddr == NULL) { switch (isc_sockaddr_pf(destaddr)) { @@ -597,24 +569,10 @@ find_udp_dispatch(dns_requestmgr_t *requestmgr, const isc_sockaddr_t *srcaddr, dns_dispatch_attach(disp, dispatchp); return (ISC_R_SUCCESS); } - attrs = DNS_DISPATCHATTR_UDP; - switch (isc_sockaddr_pf(srcaddr)) { - case PF_INET: - attrs |= DNS_DISPATCHATTR_IPV4; - break; - case PF_INET6: - attrs |= DNS_DISPATCHATTR_IPV6; - break; - - default: - return (ISC_R_NOTIMPLEMENTED); - } - - return (dns_dispatch_createudp(requestmgr->dispatchmgr, - requestmgr->socketmgr, - requestmgr->taskmgr, srcaddr, 32768, - 32768, 16411, 16433, attrs, dispatchp)); + return (dns_dispatch_createudp( + requestmgr->dispatchmgr, requestmgr->socketmgr, + requestmgr->taskmgr, srcaddr, 0, dispatchp)); } static isc_result_t @@ -624,12 +582,10 @@ get_dispatch(bool tcp, bool newtcp, dns_requestmgr_t *requestmgr, isc_result_t result; if (tcp) { - result = create_tcp_dispatch(newtcp, requestmgr, srcaddr, - destaddr, dscp, connected, - dispatchp); + result = tcp_dispatch(newtcp, requestmgr, srcaddr, destaddr, + dscp, connected, dispatchp); } else { - result = find_udp_dispatch(requestmgr, srcaddr, destaddr, - dispatchp); + result = udp_dispatch(requestmgr, srcaddr, destaddr, dispatchp); } return (result); } @@ -760,7 +716,7 @@ again: goto cleanup; } - sock = req_getsocket(request); + sock = dns_dispatch_getentrysocket(request->dispentry); INSIST(sock != NULL); isc_buffer_allocate(mctx, &request->query, r.length + (tcp ? 2 : 0)); @@ -931,7 +887,7 @@ use_tcp: if (result != ISC_R_SUCCESS) { goto cleanup; } - sock = req_getsocket(request); + sock = dns_dispatch_getentrysocket(request->dispentry); INSIST(sock != NULL); message->id = id; @@ -1240,12 +1196,6 @@ dns_request_destroy(dns_request_t **requestp) { /*** *** Private: request. ***/ - -static isc_socket_t * -req_getsocket(dns_request_t *request) { - return (dns_dispatch_getentrysocket(request->dispentry)); -} - static void req_connected(isc_task_t *task, isc_event_t *event) { isc_socketevent_t *sevent = (isc_socketevent_t *)event; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 14f82f3a73..9a39175319 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -2140,15 +2140,11 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, */ } else { if (have_addr) { - unsigned int attrs; - attrs = DNS_DISPATCHATTR_UDP; switch (isc_sockaddr_pf(&addr)) { case AF_INET: - attrs |= DNS_DISPATCHATTR_IPV4; dscp = dns_resolver_getquerydscp4(fctx->res); break; case AF_INET6: - attrs |= DNS_DISPATCHATTR_IPV6; dscp = dns_resolver_getquerydscp6(fctx->res); break; default: @@ -2157,8 +2153,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, } result = dns_dispatch_createudp( res->dispatchmgr, res->socketmgr, res->taskmgr, - &addr, 20000, 32768, 16411, 16433, attrs, - &query->dispatch); + &addr, 0, &query->dispatch); if (result != ISC_R_SUCCESS) { goto cleanup_query; } @@ -2941,7 +2936,6 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { bool retry = false; isc_interval_t interval; isc_result_t result; - unsigned int attrs; fetchctx_t *fctx; REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); @@ -2970,6 +2964,8 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { isc_socket_detach(&query->tcpsocket); resquery_destroy(&query); } else { + int attrs = 0; + switch (sevent->result) { case ISC_R_SUCCESS: @@ -2997,20 +2993,11 @@ resquery_connected(isc_task_t *task, isc_event_t *event) { * We are connected. Create a dispatcher and * send the query. */ - attrs = DNS_DISPATCHATTR_TCP | - DNS_DISPATCHATTR_PRIVATE | - DNS_DISPATCHATTR_CONNECTED; - if (isc_sockaddr_pf(&query->addrinfo->sockaddr) == - AF_INET) { - attrs |= DNS_DISPATCHATTR_IPV4; - } else { - attrs |= DNS_DISPATCHATTR_IPV6; - } - + attrs = DNS_DISPATCHATTR_CONNECTED; result = dns_dispatch_createtcp( query->dispatchmgr, query->tcpsocket, - query->fctx->res->taskmgr, NULL, NULL, 4096, 2, - 1, 1, 3, attrs, &query->dispatch); + query->fctx->res->taskmgr, NULL, NULL, attrs, + &query->dispatch); /* * Regardless of whether dns_dispatch_create() diff --git a/lib/dns/tests/dispatch_test.c b/lib/dns/tests/dispatch_test.c index fb79fcf40b..aa92f4ed87 100644 --- a/lib/dns/tests/dispatch_test.c +++ b/lib/dns/tests/dispatch_test.c @@ -66,7 +66,6 @@ static isc_result_t make_dispatchset(unsigned int ndisps) { isc_result_t result; isc_sockaddr_t any; - unsigned int attrs; dns_dispatch_t *disp = NULL; result = dns_dispatchmgr_create(dt_mctx, &dispatchmgr); @@ -75,9 +74,8 @@ make_dispatchset(unsigned int ndisps) { } isc_sockaddr_any(&any); - attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &any, - 6, 1024, 17, 19, attrs, &disp); + 0, &disp); if (result != ISC_R_SUCCESS) { return (result); } @@ -258,7 +256,6 @@ dispatch_getnext(void **state) { uint16_t id; struct in_addr ina; unsigned char message[12]; - unsigned int attrs; unsigned char rbuf[12]; UNUSED(state); @@ -273,9 +270,8 @@ dispatch_getnext(void **state) { ina.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&local, &ina, 0); - attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP; result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local, - 6, 1024, 17, 19, attrs, &dispatch); + 0, &dispatch); assert_int_equal(result, ISC_R_SUCCESS); /* diff --git a/lib/dns/tests/resolver_test.c b/lib/dns/tests/resolver_test.c index 5b4b7e8b81..1a6e0f6143 100644 --- a/lib/dns/tests/resolver_test.c +++ b/lib/dns/tests/resolver_test.c @@ -58,7 +58,7 @@ _setup(void **state) { isc_sockaddr_any(&local); result = dns_dispatch_createudp(dispatchmgr, socketmgr, taskmgr, &local, - 100, 100, 100, 500, 0, &dispatch); + 0, &dispatch); assert_int_equal(result, ISC_R_SUCCESS); return (0); diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h index ad6cf29603..23630bdaa5 100644 --- a/lib/isc/include/isc/socket.h +++ b/lib/isc/include/isc/socket.h @@ -225,12 +225,6 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, *\li #ISC_R_UNEXPECTED */ -isc_result_t -isc_socket_dup(isc_socket_t *sock0, isc_socket_t **socketp); -/*%< - * Duplicate an existing socket, reusing its file descriptor. - */ - void isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how); /*%< diff --git a/lib/isc/socket.c b/lib/isc/socket.c index 12d8c71550..c28b32165c 100644 --- a/lib/isc/socket.c +++ b/lib/isc/socket.c @@ -350,8 +350,8 @@ struct isc_socket { unsigned int listener : 1, /* listener socket */ connected : 1, connecting : 1, /* connect pending * */ - bound : 1, /* bound to local addr */ - dupped : 1, active : 1, /* currently active */ + bound : 1, /* bound to local addr */ + active : 1, /* currently active */ pktdscp : 1; /* per packet dscp */ #ifdef ISC_PLATFORM_RECVOVERFLOW @@ -434,7 +434,7 @@ struct isc__socketthread { static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, - isc_socket_t **socketp, isc_socket_t *dup_socket); + isc_socket_t **socketp); static void send_recvdone_event(isc_socket_t *, isc_socketevent_t **); static void @@ -1881,7 +1881,6 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type, sock->fd = -1; sock->threadid = -1; sock->dscp = 0; /* TOS/TCLASS is zero until set. */ - sock->dupped = 0; sock->statsindex = NULL; sock->active = 0; @@ -2123,8 +2122,7 @@ set_ip_disable_pmtud(isc_socket_t *sock) { } static isc_result_t -opensocket(isc_socketmgr_t *manager, isc_socket_t *sock, - isc_socket_t *dup_socket) { +opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) { isc_result_t result; char strbuf[ISC_STRERRORSIZE]; const char *err = "socket"; @@ -2138,60 +2136,52 @@ opensocket(isc_socketmgr_t *manager, isc_socket_t *sock, #endif again: - if (dup_socket == NULL) { - switch (sock->type) { - case isc_sockettype_udp: - sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP); - break; - case isc_sockettype_tcp: - sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); - break; - case isc_sockettype_unix: - sock->fd = socket(sock->pf, SOCK_STREAM, 0); - break; - case isc_sockettype_raw: - errno = EPFNOSUPPORT; - /* - * PF_ROUTE is a alias for PF_NETLINK on linux. - */ + switch (sock->type) { + case isc_sockettype_udp: + sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP); + break; + case isc_sockettype_tcp: + sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP); + break; + case isc_sockettype_unix: + sock->fd = socket(sock->pf, SOCK_STREAM, 0); + break; + case isc_sockettype_raw: + errno = EPFNOSUPPORT; + /* + * PF_ROUTE is a alias for PF_NETLINK on linux. + */ #if defined(PF_ROUTE) - if (sock->fd == -1 && sock->pf == PF_ROUTE) { + if (sock->fd == -1 && sock->pf == PF_ROUTE) { #ifdef NETLINK_ROUTE - sock->fd = socket(sock->pf, SOCK_RAW, - NETLINK_ROUTE); + sock->fd = socket(sock->pf, SOCK_RAW, NETLINK_ROUTE); #else /* ifdef NETLINK_ROUTE */ - sock->fd = socket(sock->pf, SOCK_RAW, 0); + sock->fd = socket(sock->pf, SOCK_RAW, 0); #endif /* ifdef NETLINK_ROUTE */ - if (sock->fd != -1) { + if (sock->fd != -1) { #ifdef NETLINK_ROUTE - struct sockaddr_nl sa; - int n; + struct sockaddr_nl sa; + int n; - /* - * Do an implicit bind. - */ - memset(&sa, 0, sizeof(sa)); - sa.nl_family = AF_NETLINK; - sa.nl_groups = RTMGRP_IPV4_IFADDR | - RTMGRP_IPV6_IFADDR; - n = bind(sock->fd, - (struct sockaddr *)&sa, - sizeof(sa)); - if (n < 0) { - close(sock->fd); - sock->fd = -1; - } -#endif /* ifdef NETLINK_ROUTE */ - sock->bound = 1; + /* + * Do an implicit bind. + */ + memset(&sa, 0, sizeof(sa)); + sa.nl_family = AF_NETLINK; + sa.nl_groups = RTMGRP_IPV4_IFADDR | + RTMGRP_IPV6_IFADDR; + n = bind(sock->fd, (struct sockaddr *)&sa, + sizeof(sa)); + if (n < 0) { + close(sock->fd); + sock->fd = -1; } +#endif /* ifdef NETLINK_ROUTE */ + sock->bound = 1; } -#endif /* if defined(PF_ROUTE) */ - break; } - } else { - sock->fd = dup(dup_socket->fd); - sock->dupped = 1; - sock->bound = dup_socket->bound; +#endif /* if defined(PF_ROUTE) */ + break; } if (sock->fd == -1 && errno == EINTR && tries++ < 42) { goto again; @@ -2268,10 +2258,6 @@ again: } } - if (dup_socket != NULL) { - goto setup_done; - } - result = make_nonblock(sock->fd); if (result != ISC_R_SUCCESS) { (void)close(sock->fd); @@ -2410,7 +2396,6 @@ again: set_ip_disable_pmtud(sock); -setup_done: inc_stats(manager->stats, sock->statsindex[STATID_OPEN]); if (sock->active == 0) { inc_stats(manager->stats, sock->statsindex[STATID_ACTIVE]); @@ -2421,14 +2406,13 @@ setup_done: } /* - * Create a 'type' socket or duplicate an existing socket, managed - * by 'manager'. Events will be posted to 'task' and when dispatched - * 'action' will be called with 'arg' as the arg value. The new - * socket is returned in 'socketp'. + * Create a 'type' socket, managed by 'manager'. Events will be posted to + * 'task' and when dispatched 'action' will be called with 'arg' as the arg + * value. The new socket is returned in 'socketp'. */ static isc_result_t socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, - isc_socket_t **socketp, isc_socket_t *dup_socket) { + isc_socket_t **socketp) { isc_socket_t *sock = NULL; isc__socketthread_t *thread; isc_result_t result; @@ -2466,7 +2450,7 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, sock->pf = pf; - result = opensocket(manager, sock, dup_socket); + result = opensocket(manager, sock); if (result != ISC_R_SUCCESS) { free_socket(&sock); return (result); @@ -2507,8 +2491,7 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, #endif /* ifdef USE_SELECT */ UNLOCK(&manager->lock); - socket_log(sock, NULL, CREATION, - dup_socket != NULL ? "dupped" : "created"); + socket_log(sock, NULL, CREATION, "created"); return (ISC_R_SUCCESS); } @@ -2520,22 +2503,9 @@ socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, * in 'socketp'. */ isc_result_t -isc_socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type, +isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type, isc_socket_t **socketp) { - return (socket_create(manager0, pf, type, socketp, NULL)); -} - -/*% - * Duplicate an existing socket. The new socket is returned - * in 'socketp'. - */ -isc_result_t -isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) { - REQUIRE(VALID_SOCKET(sock)); - REQUIRE(socketp != NULL && *socketp == NULL); - - return (socket_create(sock->manager, sock->pf, sock->type, socketp, - sock)); + return (socket_create(manager, pf, type, socketp)); } isc_result_t @@ -2551,7 +2521,7 @@ isc_socket_open(isc_socket_t *sock) { REQUIRE(sock->fd == -1); REQUIRE(sock->threadid == -1); - result = opensocket(sock->manager, sock, NULL); + result = opensocket(sock->manager, sock); UNLOCK(&sock->lock); @@ -2642,7 +2612,6 @@ isc_socket_close(isc_socket_t *sock) { sock->fd = -1; sock->threadid = -1; - sock->dupped = 0; memset(sock->name, 0, sizeof(sock->name)); sock->tag = NULL; sock->listener = 0; @@ -4334,7 +4303,6 @@ isc_socket_bind(isc_socket_t *sock, const isc_sockaddr_t *sockaddr, LOCK(&sock->lock); INSIST(!sock->bound); - INSIST(!sock->dupped); if (sock->pf != sockaddr->type.sa.sa_family) { UNLOCK(&sock->lock); @@ -5078,7 +5046,6 @@ isc_socket_ipv6only(isc_socket_t *sock, bool yes) { #endif /* if defined(IPV6_V6ONLY) */ REQUIRE(VALID_SOCKET(sock)); - INSIST(!sock->dupped); #ifdef IPV6_V6ONLY if (sock->pf == AF_INET6) { @@ -5151,10 +5118,6 @@ isc_socket_dscp(isc_socket_t *sock, isc_dscp_t dscp) { } #endif /* if !defined(IP_TOS) && !defined(IPV6_TCLASS) */ -#ifdef notyet - REQUIRE(!sock->dupped); -#endif /* ifdef notyet */ - setdscp(sock, dscp); } @@ -5200,8 +5163,7 @@ static void init_hasreuseport(void) { /* * SO_REUSEPORT works very differently on *BSD and on Linux (because why not). - * We only want to use it on Linux, if it's available. On BSD we want to dup() - * sockets instead of re-binding them. + * We only want to use it on Linux, if it's available. */ #if (defined(SO_REUSEPORT) && defined(__linux__)) || \ (defined(SO_REUSEPORT_LB) && defined(__FreeBSD_kernel__)) diff --git a/lib/isc/tests/socket_test.c b/lib/isc/tests/socket_test.c index 285e3c86ab..a98fc11906 100644 --- a/lib/isc/tests/socket_test.c +++ b/lib/isc/tests/socket_test.c @@ -218,89 +218,6 @@ udp_sendto_test(void **state) { assert_string_equal(recvbuf, "Hello"); } -/* Test UDP sendto/recv with duplicated socket */ -static void -udp_dup_test(void **state) { - isc_result_t result; - isc_sockaddr_t addr1, addr2; - struct in_addr in; - char sendbuf[BUFSIZ], recvbuf[BUFSIZ]; - completion_t completion; - isc_region_t r; - - UNUSED(state); - - in.s_addr = inet_addr("127.0.0.1"); - isc_sockaddr_fromin(&addr1, &in, 0); - isc_sockaddr_fromin(&addr2, &in, 0); - - result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1); - assert_int_equal(result, ISC_R_SUCCESS); - result = isc_socket_bind(s1, &addr1, 0); - assert_int_equal(result, ISC_R_SUCCESS); - result = isc_socket_getsockname(s1, &addr1); - assert_int_equal(result, ISC_R_SUCCESS); - assert_true(isc_sockaddr_getport(&addr1) != 0); - - result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2); - assert_int_equal(result, ISC_R_SUCCESS); - result = isc_socket_bind(s2, &addr2, 0); - assert_int_equal(result, ISC_R_SUCCESS); - result = isc_socket_getsockname(s2, &addr2); - assert_int_equal(result, ISC_R_SUCCESS); - assert_true(isc_sockaddr_getport(&addr2) != 0); - - result = isc_socket_dup(s2, &s3); - assert_int_equal(result, ISC_R_SUCCESS); - - result = isc_task_create(taskmgr, 0, &test_task); - assert_int_equal(result, ISC_R_SUCCESS); - - snprintf(sendbuf, sizeof(sendbuf), "Hello"); - r.base = (void *)sendbuf; - r.length = strlen(sendbuf) + 1; - - completion_init(&completion); - result = isc_socket_sendto(s1, &r, test_task, event_done, &completion, - &addr2, NULL); - assert_int_equal(result, ISC_R_SUCCESS); - waitfor(&completion); - assert_true(atomic_load(&completion.done)); - assert_int_equal(completion.result, ISC_R_SUCCESS); - - snprintf(sendbuf, sizeof(sendbuf), "World"); - r.base = (void *)sendbuf; - r.length = strlen(sendbuf) + 1; - - completion_init(&completion); - result = isc_socket_sendto(s1, &r, test_task, event_done, &completion, - &addr2, NULL); - assert_int_equal(result, ISC_R_SUCCESS); - waitfor(&completion); - assert_true(atomic_load(&completion.done)); - assert_int_equal(completion.result, ISC_R_SUCCESS); - - r.base = (void *)recvbuf; - r.length = BUFSIZ; - completion_init(&completion); - result = isc_socket_recv(s2, &r, 1, test_task, event_done, &completion); - assert_int_equal(result, ISC_R_SUCCESS); - waitfor(&completion); - assert_true(atomic_load(&completion.done)); - assert_int_equal(completion.result, ISC_R_SUCCESS); - assert_string_equal(recvbuf, "Hello"); - - r.base = (void *)recvbuf; - r.length = BUFSIZ; - completion_init(&completion); - result = isc_socket_recv(s3, &r, 1, test_task, event_done, &completion); - assert_int_equal(result, ISC_R_SUCCESS); - waitfor(&completion); - assert_true(atomic_load(&completion.done)); - assert_int_equal(completion.result, ISC_R_SUCCESS); - assert_string_equal(recvbuf, "World"); -} - /* Test UDP sendto/recv (IPv4) */ static void udp_dscp_v4_test(void **state) { @@ -787,8 +704,6 @@ main(void) { const struct CMUnitTest tests[] = { cmocka_unit_test_setup_teardown(udp_sendto_test, _setup, _teardown), - cmocka_unit_test_setup_teardown(udp_dup_test, _setup, - _teardown), cmocka_unit_test_setup_teardown(tcp_dscp_v4_test, _setup, _teardown), cmocka_unit_test_setup_teardown(tcp_dscp_v6_test, _setup,