diff --git a/bin/named/client.c b/bin/named/client.c index 216995426f..fdf4fcd929 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -102,7 +102,15 @@ #define SEND_BUFFER_SIZE 4096 #define RECV_BUFFER_SIZE 4096 +#define TCP_CLIENTS_PER_CONN 23 +/*%< + * Number of simultaneous ns_clients_t (queries in flight) for one + * TCP connection. The number was arbitrarily picked and might be + * changed in the future. + */ + #ifdef ISC_PLATFORM_USETHREADS + #define NMCTXS 100 /*%< * Number of 'mctx pools' for clients. (Should this be configurable?) @@ -342,7 +350,7 @@ tcpconn_init(ns_client_t *client, bool force) { return (ISC_R_NOMEMORY); } - isc_refcount_init(&tconn->refs, 1); + isc_refcount_init(&tconn->clients, 1); /* Current client */ tconn->tcpquota = quota; quota = NULL; tconn->pipelined = false; @@ -359,14 +367,14 @@ tcpconn_init(ns_client_t *client, bool force) { */ static void tcpconn_attach(ns_client_t *source, ns_client_t *target) { - int refs; + int old_clients; REQUIRE(source->tcpconn != NULL); REQUIRE(target->tcpconn == NULL); REQUIRE(source->tcpconn->pipelined); - isc_refcount_increment(&source->tcpconn->refs, &refs); - INSIST(refs > 1); + isc_refcount_increment(&source->tcpconn->clients, &old_clients); + INSIST(old_clients > 1); target->tcpconn = source->tcpconn; } @@ -379,15 +387,15 @@ tcpconn_attach(ns_client_t *source, ns_client_t *target) { static void tcpconn_detach(ns_client_t *client) { ns_tcpconn_t *tconn = NULL; - int refs; + int old_clients; REQUIRE(client->tcpconn != NULL); tconn = client->tcpconn; client->tcpconn = NULL; - isc_refcount_decrement(&tconn->refs, &refs); - if (refs == 0) { + isc_refcount_decrement(&tconn->clients, &old_clients); + if (old_clients == 0) { isc_quota_detach(&tconn->tcpquota); isc_mem_free(ns_g_mctx, tconn); } @@ -2683,28 +2691,39 @@ client_request(isc_task_t *task, isc_event_t *event) { /* * Pipeline TCP query processing. */ - if (TCP_CLIENT(client) && - client->message->opcode != dns_opcode_query) - { - client->tcpconn->pipelined = false; - } - if (TCP_CLIENT(client) && client->tcpconn->pipelined) { + if (TCP_CLIENT(client)) { + if (client->message->opcode != dns_opcode_query) { + client->tcpconn->pipelined = false; + } + /* - * We're pipelining. Replace the client; the - * replacement can read the TCP socket looking - * for new messages and this one can process the - * current message asynchronously. - * - * There will now be at least three clients using this - * TCP socket - one accepting new connections, - * one reading an existing connection to get new - * messages, and one answering the message already - * received. + * Limit the maximum number of simultaneous pipelined + * queries on TCP connection to TCP_CLIENTS_PER_CONN. */ - result = ns_client_replace(client); - if (result != ISC_R_SUCCESS) { + if ((isc_refcount_current(&client->tcpconn->clients) + > TCP_CLIENTS_PER_CONN)) + { client->tcpconn->pipelined = false; } + + if (client->tcpconn->pipelined) { + /* + * We're pipelining. Replace the client; the + * replacement can read the TCP socket looking + * for new messages and this one can process the + * current message asynchronously. + * + * There will now be at least three clients using this + * TCP socket - one accepting new connections, + * one reading an existing connection to get new + * messages, and one answering the message already + * received. + */ + result = ns_client_replace(client); + if (result != ISC_R_SUCCESS) { + client->tcpconn->pipelined = false; + } + } } dns_opcodestats_increment(ns_g_server->opcodestats, diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 969ee4c08f..01b6141c99 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -80,7 +80,10 @@ /*% reference-counted TCP connection object */ typedef struct ns_tcpconn { - isc_refcount_t refs; + isc_refcount_t clients; /* Number of clients using + * this connection. Conn can + * be freed if goes to 0 + */ isc_quota_t *tcpquota; bool pipelined; } ns_tcpconn_t;