dnsbuf – Dynamically Set the DNS UDP Buffer Size
**Configuration Change. ** This feature is available in Momentum 4.2 and later.
Momentum does not manipulate the size of UDP sockets it creates and uses for DNS queries; instead, it will use the default sizes configured by the Operating System. This can create problems for clients with too many domains (e.g., tens of thousands) in the system. Responses may be dropped, causing unnecessary DNS failures and retries, thus further increasing the DNS query volume. The dnsbuf
module enables the client to manipulate the DNS buffer sizes on demand, on the fly.
The dnsbuf
module is configured as follows:
dnsbuf {
sndbuf_size = "65536" # Default value is 131072
rcvbuf_size = "65536" # Default value is 131072
interval = "30" # Default value is 60 seconds
}
- sndbuf_size
-
The SO_SNDBUF value is set to this value for all UDP DNS sockets in the Momentum DNS implementation. Minimum value is 1024. Note that in Linux the value in the kernel is automatically doubled; e.g., when a value of 65536 is configured in the module, the kernel will implement a buffer size of 131072.
- rcvbuf_size
-
The SO_RCVBUF value is set to this value for all UDP DNS sockets in the Momentum DNS implementation. Minimum value is 1024. Note that in Linux the value in the kernel is automatically doubled; e.g., when a value of 65536 is configured in the module, the kernel will actually implement a buffer size of 131072.
- interval
-
This parameter determines how often the
setsockopt()
operations are performed. This process must be performed on a periodic basis as there is no hook point available in the system that allows the task to be performed when new UDP DNS sockets are created. The value is defined in terms of seconds.
The following console commands are specific to the dnsbuf
module.
- config set dnsbuf sndbuf_size *`xxx`*
-
Change the
sndbuf_size
value on the fly toxxx
. This does not persist after a restart of Ecelerity; therefore, the configuration file must also be changed. Note that the change to the DNS socket buffer sizes is not immediate. Those values will not change until the next interval as described previously. - config set dnsbuf rcvbuf_size *`xxx`*
-
Change the
rcvbuf_size
value on the fly toxxx
. This does not persist after a restart of Ecelerity; therefore, the configuration file must also be changed. Note that the change to the DNS socket buffer sizes is not immediate. Those values will not change until the next interval as described previously. - config set dnsbuf interval *`xxx`*
-
Change how often the
setsockopt()
operations are performed. This change is not honored until the next automatic run; e.g., if the previous value was 60 and you call 'dnsbuf interval 10' 30 seconds after the last run happened, the next run will not happen for 30 seconds, but subsequent runs will happen every 10 seconds. - dnsbuf verify
-
Using
getsockopt()
, query all active sockets for their current buffer sizes and report the results. These are the actual values reported by the kernel, and take into account the doubling behavior described previously. These values may not reflect recent changes made to the configured values in thednsbuf
module as the next periodicsetsockopt()
may not have been called yet.
The following are subtleties associated with the dnsbuf
module:
-
When the system starts up, it is common to fail on the first attempt to update the buffer sizes. While the DNS system is initialized on startup, the UDP sockets are not actually created until the first DNS query is pushed into the system. Therefore, if a dnsbuf verify is performed right after startup it will likely report the system default settings.
-
Worst case, it will take 60 seconds from when the first email message is processed by the system to when the DNS buffer sizes are raised. The interval could be made smaller, although there is a risk that running the
setsockopt()
routines too often could reduce performance. -
Server numbers are indexed based on their order in the
resolv.conf
file. So server 0 represents the firstnameserver
line, server 1 represents the secondnameserver
line, and so on. -
The buffer cannot be set beyond the sysctl-defined maximums in Linux:
net.core.rmem_max net.core.wmem_max
Note that those values are the post-doubled values; e.g., if
net.core.wmem_max
is set to 65536, the maximum value that will work in thednsbuf
module issndbuf_max
= 32768.
The following are limitations of the dnsbuf
module:
-
Alternative DNS resolution channels are used by the Sieve
ec_dns_lookup
action when a custom server is specified, e.g.:$result = ec_dns_lookup "foo.com" "a" "ns.foo.com";
-
The module can only modify the buffer sizes for the primary DNS resolution channel. This module cannot alter the UDP buffer size for alternative DNS resolution channels.
To determine whether the DNS responses are being dropped because the DNS UDP socket buffer is full, look for a corresponding increase in the "Pending DNS Queries" statistic from Momentum and the UDP packet errors from netstat, e.g.:
while sleep 1; do (netstat --udp -s | grep error; echo summary | /opt/msys/ecelerity/bin/ec_console | grep DNS); echo; done
The following is an example in which Momentum started with ~30,000 unresolvable domains in the queue. Notice that the "packet receive errors" number has increased, and there are a high number of pending DNS queries.
1559857 packet receive errors DNS A Queries: 924801 DNS AAAA Queries: 0 DNS MX Queries: 907577 Pending DNS Queries: 312 1559857 packet receive errors DNS A Queries: 924803 DNS AAAA Queries: 0 DNS MX Queries: 907849 Pending DNS Queries: 43 1560125 packet receive errors DNS A Queries: 924803 DNS AAAA Queries: 0 DNS MX Queries: 908388 Pending DNS Queries: 311