extern unsigned int dns_adb_entrywindow;
extern unsigned int dns_adb_cachemin;
+extern size_t dns_dispatch_tcppipelining;
static bool want_stats = false;
static char absolute_conffile[PATH_MAX];
dns_adb_entrywindow = atoi(option + 15);
} else if (!strncmp(option, "adbcachemin=", 12)) {
dns_adb_cachemin = atoi(option + 12);
+ } else if (!strncmp(option, "tcppipelining=", 14)) {
+ size_t pipelining = atoi(option + 14);
+ if (pipelining < 1) {
+ named_main_earlyfatal("tcppipelining must be at "
+ "least 1");
+ }
+ dns_dispatch_tcppipelining = pipelining;
} else {
fprintf(stderr, "unknown -T flag '%s'\n", option);
}
#include <dns/transport.h>
#include <dns/types.h>
+/*
+ * Maximum number of queries to pipeline on a single shared TCP dispatch.
+ * Once reached, the dispatch is removed from the hash table so new queries
+ * get a fresh connection. Can be overridden via 'named -T tcppipelining=N'.
+ */
+size_t dns_dispatch_tcppipelining = 256;
+
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
struct dns_dispatchmgr {
disp->requests++;
+ /*
+ * If this shared TCP dispatch has reached the pipelining limit,
+ * remove it from the hash table so new queries get a fresh
+ * connection. The dispatch continues to serve its existing
+ * queries until they complete.
+ */
+ if (disp->socktype == isc_socktype_tcp &&
+ (disp->options & DNS_DISPATCHOPT_FIXEDID) == 0 &&
+ disp->requests >= dns_dispatch_tcppipelining)
+ {
+ (void)cds_lfht_del(disp->mgr->tcps[isc_tid()], &disp->ht_node);
+ }
+
inc_stats(disp->mgr, (disp->socktype == isc_socktype_udp)
? dns_resstatscounter_disprequdp
: dns_resstatscounter_dispreqtcp);