diff --git a/lib/ns/client.c b/lib/ns/client.c index 0efe59a13c..c1bd2c7a1d 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -103,6 +103,13 @@ #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. + */ + #define NMCTXS 100 /*%< * Number of 'mctx pools' for clients. (Should this be configurable?) @@ -357,7 +364,7 @@ tcpconn_init(ns_client_t *client, bool force) { */ tconn = isc_mem_allocate(client->sctx->mctx, sizeof(*tconn)); - isc_refcount_init(&tconn->refs, 1); + isc_refcount_init(&tconn->clients, 1); /* Current client */ tconn->tcpquota = quota; quota = NULL; tconn->pipelined = false; @@ -374,14 +381,14 @@ tcpconn_init(ns_client_t *client, bool force) { */ static void tcpconn_attach(ns_client_t *source, ns_client_t *target) { - int old_refs; + int old_clients; REQUIRE(source->tcpconn != NULL); REQUIRE(target->tcpconn == NULL); REQUIRE(source->tcpconn->pipelined); - old_refs = isc_refcount_increment(&source->tcpconn->refs); - INSIST(old_refs > 0); + old_clients = isc_refcount_increment(&source->tcpconn->clients); + INSIST(old_clients > 0); target->tcpconn = source->tcpconn; } @@ -394,17 +401,17 @@ tcpconn_attach(ns_client_t *source, ns_client_t *target) { static void tcpconn_detach(ns_client_t *client) { ns_tcpconn_t *tconn = NULL; - int old_refs; + int old_clients; REQUIRE(client->tcpconn != NULL); tconn = client->tcpconn; client->tcpconn = NULL; - old_refs = isc_refcount_decrement(&tconn->refs); - INSIST(old_refs > 0); + old_clients = isc_refcount_decrement(&tconn->clients); + INSIST(old_clients > 0); - if (old_refs == 1) { + if (old_clients == 1) { isc_quota_detach(&tconn->tcpquota); isc_mem_free(client->sctx->mctx, tconn); } @@ -2666,28 +2673,39 @@ ns__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(client->sctx->opcodestats, diff --git a/lib/ns/include/ns/client.h b/lib/ns/include/ns/client.h index 110d25e953..56a48646f7 100644 --- a/lib/ns/include/ns/client.h +++ b/lib/ns/include/ns/client.h @@ -82,7 +82,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;