tcp-initial-timeout 300;\n\
tcp-keepalive-timeout 300;\n\
tcp-listen-queue 10;\n\
+ tcp-receive-buffer 0;\n\
+ tcp-send-buffer 0;\n\
# tkey-dhkey <none>\n\
# tkey-domain <none>\n\
# tkey-gssapi-credential <none>\n\
# treat-cr-as-space <obsolete>;\n\
trust-anchor-telemetry yes;\n\
# use-id-pool <obsolete>;\n\
+ udp-receive-buffer 0;\n\
+ udp-send-buffer 0;\n\
\n\
/* view */\n\
allow-new-zones no;\n\
tcp-initial-timeout integer;
tcp-keepalive-timeout integer;
tcp-listen-queue integer;
+ tcp-receive-buffer integer;
+ tcp-send-buffer integer;
tkey-dhkey quoted_string integer;
tkey-domain quoted_string;
tkey-gssapi-credential quoted_string;
transfers-per-ns integer;
trust-anchor-telemetry boolean; // experimental
try-tcp-refresh boolean;
+ udp-receive-buffer integer;
+ udp-send-buffer integer;
update-check-ksk boolean;
use-alt-transfer-source boolean;
use-v4-udp-ports { portrange; ... };
uint32_t reserved;
uint32_t udpsize;
uint32_t transfer_message_size;
+ uint32_t recv_tcp_buffer_size;
+ uint32_t send_tcp_buffer_size;
+ uint32_t recv_udp_buffer_size;
+ uint32_t send_udp_buffer_size;
named_cache_t *nsc;
named_cachelist_t cachelist, tmpcachelist;
ns_altsecret_t *altsecret;
named_g_aclconfctx),
"configuring statistics server(s)");
+ /*
+ * Configure the network manager
+ */
obj = NULL;
result = named_config_get(maps, "tcp-initial-timeout", &obj);
INSIST(result == ISC_R_SUCCESS);
isc_nm_settimeouts(named_g_netmgr, initial, idle, keepalive,
advertised);
+#define CAP_IF_NOT_ZERO(v, min, max) \
+ if (v > 0 && v < min) { \
+ recv_tcp_buffer_size = min; \
+ } else if (v > max) { \
+ recv_tcp_buffer_size = max; \
+ }
+
+ /* Set the kernel send and receive buffer sizes */
+ obj = NULL;
+ result = named_config_get(maps, "tcp-receive-buffer", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ recv_tcp_buffer_size = cfg_obj_asuint32(obj);
+ CAP_IF_NOT_ZERO(recv_tcp_buffer_size, 4096, INT32_MAX);
+
+ obj = NULL;
+ result = named_config_get(maps, "tcp-send-buffer", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ send_tcp_buffer_size = cfg_obj_asuint32(obj);
+ CAP_IF_NOT_ZERO(send_tcp_buffer_size, 4096, INT32_MAX);
+
+ obj = NULL;
+ result = named_config_get(maps, "udp-receive-buffer", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ recv_udp_buffer_size = cfg_obj_asuint32(obj);
+ CAP_IF_NOT_ZERO(recv_udp_buffer_size, 4096, INT32_MAX);
+
+ obj = NULL;
+ result = named_config_get(maps, "udp-send-buffer", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ send_udp_buffer_size = cfg_obj_asuint32(obj);
+ CAP_IF_NOT_ZERO(send_udp_buffer_size, 4096, INT32_MAX);
+
+ isc_nm_setnetbuffers(named_g_netmgr, recv_tcp_buffer_size,
+ send_tcp_buffer_size, recv_udp_buffer_size,
+ send_udp_buffer_size);
+
+#undef CAP_IF_NOT_ZERO
+
/*
* Configure sets of UDP query source ports.
*/
milliseconds to prefer IPv6 name servers. The default is ``50``
milliseconds.
+``tcp-recv-buffer``; ``udp-recv-buffer``
+ These options control the operating system receiving network buffer sizes for
+ TCP and UDP respectively. Buffering on the operating system level can
+ prevent packet drops during short spikes, but if the value is set too large
+ it could clog up a running server with outstanding queries that have already
+ timeouted. The default is ``0`` which means to use the operating system
+ default value. The operating system caps the maximum value that the user can
+ set here.
+
+``tcp-send-buffer``; ``udp-send-buffer``
+ These options control the operating system sending network buffer sizes for
+ TCP and UDP respectively. Buffering on the operating system level can
+ prevent packet drops during short spikes, but if the value is set too large
+ it could clog up a running server with outstanding queries that have already
+ timeouted. The default is ``0`` which means to use the operating system
+ default value. The operating system caps the maximum value that the user can
+ set here.
+
.. _builtin:
Built-in Server Information Zones
tcp\-initial\-timeout integer;
tcp\-keepalive\-timeout integer;
tcp\-listen\-queue integer;
+ tcp\-receive\-buffer integer;
+ tcp\-send\-buffer integer;
tkey\-dhkey quoted_string integer;
tkey\-domain quoted_string;
tkey\-gssapi\-credential quoted_string;
transfers\-per\-ns integer;
trust\-anchor\-telemetry boolean; // experimental
try\-tcp\-refresh boolean;
+ udp\-receive\-buffer integer;
+ udp\-send\-buffer integer;
update\-check\-ksk boolean;
use\-alt\-transfer\-source boolean;
use\-v4\-udp\-ports { portrange; ... };
tcp-initial-timeout <integer>;
tcp-keepalive-timeout <integer>;
tcp-listen-queue <integer>;
+ tcp-receive-buffer <integer>;
+ tcp-send-buffer <integer>;
tkey-dhkey <quoted_string> <integer>;
tkey-domain <quoted_string>;
tkey-gssapi-credential <quoted_string>;
transfers-per-ns <integer>;
trust-anchor-telemetry <boolean>; // experimental
try-tcp-refresh <boolean>;
+ udp-receive-buffer <integer>;
+ udp-send-buffer <integer>;
update-check-ksk <boolean>;
use-alt-transfer-source <boolean>;
use-v4-udp-ports { <portrange>; ... };
tcp-initial-timeout <integer>;
tcp-keepalive-timeout <integer>;
tcp-listen-queue <integer>;
+ tcp-receive-buffer <integer>;
+ tcp-send-buffer <integer>;
tkey-dhkey <quoted_string> <integer>;
tkey-domain <quoted_string>;
tkey-gssapi-credential <quoted_string>;
transfers-per-ns <integer>;
trust-anchor-telemetry <boolean>; // experimental
try-tcp-refresh <boolean>;
+ udp-receive-buffer <integer>;
+ udp-send-buffer <integer>;
update-check-ksk <boolean>;
use-alt-transfer-source <boolean>;
use-v4-udp-ports { <portrange>; ... };
tcp-initial-timeout <integer>;
tcp-keepalive-timeout <integer>;
tcp-listen-queue <integer>;
+ tcp-receive-buffer <integer>;
+ tcp-send-buffer <integer>;
tkey-dhkey <quoted_string> <integer>;
tkey-domain <quoted_string>;
tkey-gssapi-credential <quoted_string>;
transfers-per-ns <integer>;
trust-anchor-telemetry <boolean>; // experimental
try-tcp-refresh <boolean>;
+ udp-receive-buffer <integer>;
+ udp-send-buffer <integer>;
update-check-ksk <boolean>;
use-alt-transfer-source <boolean>;
use-v4-udp-ports { <portrange>; ... };
* \li 'mgr' is a valid netmgr.
*/
+void
+isc_nm_setnetbuffers(isc_nm_t *mgr, int32_t recv_tcp, int32_t send_tcp,
+ int32_t recv_udp, int32_t send_udp);
+/*%<
+ * If not 0, sets the SO_RCVBUF and SO_SNDBUF socket options for TCP and UDP
+ * respectively.
+ *
+ * Requires:
+ * \li 'mgr' is a valid netmgr.
+ */
+
void
isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle,
uint32_t *keepalive, uint32_t *advertised);
isc_barrier_t pausing;
isc_barrier_t resuming;
+ /*
+ * Socket SO_RCVBUF and SO_SNDBUF values
+ */
+ atomic_int_fast32_t recv_udp_buffer_size;
+ atomic_int_fast32_t send_udp_buffer_size;
+ atomic_int_fast32_t recv_tcp_buffer_size;
+ atomic_int_fast32_t send_tcp_buffer_size;
+
#ifdef NETMGR_TRACE
ISC_LIST(isc_nmsocket_t) active_sockets;
#endif
* Disables Nagle's algorithm on a TCP socket (sets TCP_NODELAY).
*/
+void
+isc__nm_set_network_buffers(isc_nm_t *nm, uv_handle_t *handle);
+/*%>
+ * Sets the pre-configured network buffers size on the handle.
+ */
+
/*
* typedef all the netievent types
*/
atomic_store(&mgr->advertised, advertised);
}
+void
+isc_nm_setnetbuffers(isc_nm_t *mgr, int32_t recv_tcp, int32_t send_tcp,
+ int32_t recv_udp, int32_t send_udp) {
+ REQUIRE(VALID_NM(mgr));
+
+ atomic_store(&mgr->recv_tcp_buffer_size, recv_tcp);
+ atomic_store(&mgr->send_tcp_buffer_size, send_tcp);
+ atomic_store(&mgr->recv_udp_buffer_size, recv_udp);
+ atomic_store(&mgr->send_udp_buffer_size, send_udp);
+}
+
void
isc_nm_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle,
uint32_t *keepalive, uint32_t *advertised) {
#endif
}
+void
+isc__nm_set_network_buffers(isc_nm_t *nm, uv_handle_t *handle) {
+ int32_t recv_buffer_size = 0;
+ int32_t send_buffer_size = 0;
+
+ switch (handle->type) {
+ case UV_TCP:
+ recv_buffer_size =
+ atomic_load_relaxed(&nm->recv_tcp_buffer_size);
+ send_buffer_size =
+ atomic_load_relaxed(&nm->send_tcp_buffer_size);
+ break;
+ case UV_UDP:
+ recv_buffer_size =
+ atomic_load_relaxed(&nm->recv_udp_buffer_size);
+ send_buffer_size =
+ atomic_load_relaxed(&nm->send_udp_buffer_size);
+ break;
+ default:
+ INSIST(0);
+ ISC_UNREACHABLE();
+ }
+
+ if (recv_buffer_size > 0) {
+ int r = uv_recv_buffer_size(handle, &recv_buffer_size);
+ INSIST(r == 0);
+ }
+
+ if (send_buffer_size > 0) {
+ int r = uv_send_buffer_size(handle, &send_buffer_size);
+ INSIST(r == 0);
+ }
+}
+
#ifdef NETMGR_TRACE
/*
* Dump all active sockets in netmgr. We output to stderr
}
}
+ isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
+
uv_handle_set_data(&req->uv_req.handle, req);
r = uv_tcp_connect(&req->uv_req.connect, &sock->uv_handle.tcp,
&req->peer.type.sa, tcp_connect_cb);
}
#endif
+ isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
+
/*
* The callback will run in the same thread uv_listen() was called
* from, so a race with tcp_connection_cb() isn't possible.
}
}
+ isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
+
uv_handle_set_data(&req->uv_req.handle, req);
r = uv_tcp_connect(&req->uv_req.connect, &sock->uv_handle.tcp,
&req->peer.type.sa, tcpdns_connect_cb);
}
#endif
+ isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
+
/*
* The callback will run in the same thread uv_listen() was called
* from, so a race with tcpdns_connection_cb() isn't possible.
}
}
+ isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
+
uv_handle_set_data(&req->uv_req.handle, req);
r = uv_tcp_connect(&req->uv_req.connect, &sock->uv_handle.tcp,
&req->peer.type.sa, tlsdns_connect_cb);
}
#endif
+ isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
+
/*
* The callback will run in the same thread uv_listen() was
* called from, so a race with tlsdns_connection_cb() isn't
}
#endif
-#ifdef ISC_RECV_BUFFER_SIZE
- uv_recv_buffer_size(&sock->uv_handle.handle,
- &(int){ ISC_RECV_BUFFER_SIZE });
-#endif
-#ifdef ISC_SEND_BUFFER_SIZE
- uv_send_buffer_size(&sock->uv_handle.handle,
- &(int){ ISC_SEND_BUFFER_SIZE });
-#endif
+ isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
+
r = uv_udp_recv_start(&sock->uv_handle.udp, isc__nm_alloc_cb,
udp_recv_cb);
if (r != 0) {
goto done;
}
-#ifdef ISC_RECV_BUFFER_SIZE
- uv_recv_buffer_size(&sock->uv_handle.handle,
- &(int){ ISC_RECV_BUFFER_SIZE });
-#endif
-#ifdef ISC_SEND_BUFFER_SIZE
- uv_send_buffer_size(&sock->uv_handle.handle,
- &(int){ ISC_SEND_BUFFER_SIZE });
-#endif
+ isc__nm_set_network_buffers(sock->mgr, &sock->uv_handle.handle);
/*
* On FreeBSD the UDP connect() call sometimes results in a
isc_nm_tcpconnect
isc_nm_tcpdnsconnect
isc_nm_gettimeouts
+isc_nm_setnetbuffers
isc_nm_settimeouts
isc_nm_tcpdns_keepalive
isc_nm_tcpdns_sequential
{ "tcp-initial-timeout", &cfg_type_uint32, 0 },
{ "tcp-keepalive-timeout", &cfg_type_uint32, 0 },
{ "tcp-listen-queue", &cfg_type_uint32, 0 },
+ { "tcp-receive-buffer", &cfg_type_uint32, 0 },
+ { "tcp-send-buffer", &cfg_type_uint32, 0 },
{ "tkey-dhkey", &cfg_type_tkey_dhkey, 0 },
{ "tkey-domain", &cfg_type_qstring, 0 },
{ "tkey-gssapi-credential", &cfg_type_qstring, 0 },
{ "transfers-out", &cfg_type_uint32, 0 },
{ "transfers-per-ns", &cfg_type_uint32, 0 },
{ "treat-cr-as-space", NULL, CFG_CLAUSEFLAG_ANCIENT },
+ { "udp-receive-buffer", &cfg_type_uint32, 0 },
+ { "udp-send-buffer", &cfg_type_uint32, 0 },
{ "use-id-pool", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "use-ixfr", NULL, CFG_CLAUSEFLAG_ANCIENT },
{ "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },