From: Michał Kępień Date: Sun, 29 Dec 2024 09:22:20 +0000 (+0100) Subject: Improve reuse of outgoing TCP connections X-Git-Tag: v9.21.4~11^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=086c325ad3f9b54b5db57e58b6e5960e7c6b288e;p=thirdparty%2Fbind9.git Improve reuse of outgoing TCP connections The dns_dispatch_gettcp() function is used for finding an existing TCP connection that can be reused for sending a query from a specified local address to a specified remote address. The logic for matching the provided tuple to one of the existing TCP connections is implemented in the dispatch_match() function: - if the examined TCP connection already has a libuv handle assigned, it means the connection has already been established; therefore, compare the provided tuple against the corresponding address tuple for the libuv handle associated with the connection, - if the examined TCP connection does not yet have a libuv handle assigned, it means the connection has not yet been established; therefore, compare the provided tuple against the corresponding address tuple that the TCP connection was originally created for. This logic limits TCP connection reuse potential as the libuv handle assigned to an existing dispatch object may have a more specific local tuple associated with it than the local tuple that the dispatch object was originally created for. That's because the local address for outgoing connections can be set to a wildcard tuple (indicating that the caller does not care what source tuple will be used for establishing the connection, thereby delegating the task of picking it to the operating system) and then get "upgraded" to a specific tuple when the socket is bound (and a libuv handle gets associated with it). When another dns_dispatch_gettcp() caller then tries to look for an existing TCP connection to the same peer and passes a wildcard address in the local part of the tuple, the function will not match that request to a previously-established TCP connection (unless isc_nmhandle_localaddr() returns a wildcard address as well). Simplify dispatch_match() so that the libuv handle associated with an existing dispatch object is not examined for the purpose of matching it to the provided tuple; instead, always examine the tuple that the dispatch object was originally created for. This enables reuse of TCP connections created without providing a specific local socket address while still preventing other connections (created for a specific local socket address) from being inadvertently shared. --- diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 5484caffc94..6e71c5c6455 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -1152,20 +1152,11 @@ static int dispatch_match(struct cds_lfht_node *node, const void *key0) { dns_dispatch_t *disp = caa_container_of(node, dns_dispatch_t, ht_node); const struct dispatch_key *key = key0; - isc_sockaddr_t local; - isc_sockaddr_t peer; - - if (disp->handle != NULL) { - local = isc_nmhandle_localaddr(disp->handle); - peer = isc_nmhandle_peeraddr(disp->handle); - } else { - local = disp->local; - peer = disp->peer; - } - return isc_sockaddr_equal(&peer, key->peer) && - disp->transport == key->transport && - (key->local == NULL || isc_sockaddr_equal(&local, key->local)); + return disp->transport == key->transport && + isc_sockaddr_equal(&disp->peer, key->peer) && + (key->local == NULL || + isc_sockaddr_equal(&disp->local, key->local)); } isc_result_t