[ntp:questions] ntp-dev 4.2.7p22 MRU list cap raised from 600

Dave Hart davehart at gmail.com
Fri Apr 2 07:11:43 UTC 2010

ntpd maintains a "Most Recently Used" (MRU) list of source IP
addresses seen in incoming NTP packets.  This list serves two
purposes, first allowing operator monitoring of client traffic,
including the average time between packets from a given address.  This
can be seen with "ntpdc -c monlist" (or "ntpdc -nc monlist" to avoid
the delay of reversing IP addresses to names).  Second, the same MRU
list is the history used by the "restrict limited" rate-limiting

If the "limited" restriction applies to a client packet and that
client's traffic exceeds the  "discard minimum" and "discard average"
profile, a normal response packet is not sent.  Further, in that case
if the "kod" restriction also applies along with "limited", a KoD
response with refid .RATE. will be sent instead, subject to its own
rate-limiting mechanism.

However, prior to 4.2.7p22 the MRU list size was capped at 600
entries.  For a public server with thousands of clients and peaks of
hundreds of packets per second at various multiples of 5 minutes
(howdy, cron'd ntpdate), both monitoring and rate limiting functions
suffer from the short duration of the history.

Now there are a number of new ntp.conf knobs controlling the MRU size
limits.  They are (with default values):

mru initmem 4
mru incmem 4
mru maxmem 1024
mru mindepth 600
mru maxage 64


mru initmem 4 incmem 4 maxmem 1024 mindepth 600 maxage 64

This means 4 kilobytes of memory will be carved up into the initial
available entries ready to be placed on the MRU list, and when those
are exhausted 4 kB is added at a time, up to a hard limit of between
maxmem and maxmem + incmem (1028 kB or a hair over 1MB).  However,
additional entries are added only if the existing entries cannot be
reused.  The most recently seen mindepth (600) entries are protected
from recycling.  Beyond that, entries for addresses last seen more
than maxage (64) seconds ago are eligible for recycling.  The oldest
entry in the list is the only one considered for recycling.

With these defaults, as before ntpdc -c monlist, now restricted to 600
rows of response by ntpd, will show the most recent 600 source IP
addresses seen regardless of their age.  No more than 600 entries will
be kept if that always accomodates the last 64 seconds of addresses.
No more than 1MB worth (about 14,000 entries on 32-bit systems) will
be kept in total.

Here's some concrete illustration from a public server:

hart at pool1> ntpq -c monstats
enabled:              0x3
addresses:            46703
peak addresses:       46703
maximum addresses:    116508
reclaim above count:  600
reclaim older than:   600
kilobytes:            3284
maximum kilobytes:    8192

hart at pool1> ntpq -c sysstats
uptime:                 53038
sysstats reset:         53038
packets received:       3038832
current version:        1929707
older version:          811595
bad length or format:   295549
authentication failed:  3155
declined:               58
restricted:             265
rate limited:           205631
KoD responses:          27475
processed for time:     4147

pool1 uses "restrict default kod limited" as well as "discard minimum
0" (default is 1), meaning it requires at least 1s between packets
from an address, rather than the default of 2s.  This is on a server
participating in pool.ntp.org peaking at 150 packets/sec over 5 minute
intervals.  The lower minimum allows ntpdate before 4.2.7p22 to squeak
by due to 1s of slop in the enforcement.  ntpdate 4.2.7p22 works with
the default rate limiting, restraining itself to one packet every 2s
per server.

Another option for pre-4.2.7p22 ntpdate compatibility with rate
limiting is to use "restrict limited" without "kod" and with the
default "discard minimum 1" (2s).  Older ntpdate will only get one
response to use instead of 4, but the lack of a Kiss O' Death response
allows ntpdate to set the time rather than error out.

The new ntpq "mrulist" command lets you fetch arbitrarily large MRU
lists over any reasonably reliable connection (I tested using an IPv6
tunnel over UDP, for example).  Rather than use a single multipacket
response as with ntpdc's monlist, mrulist fetches a variable number of
rows in each request, starting with the oldest.  This gives a slightly
oversized list that may include some oldest entries which have fallen
off the MRU list from the server by the time the newest entries have
been fetched, but otherwise is basically a snapshot of the MRU list at
the time the newest entries are retrieved.  The number of rows fetched
per request is a tradeoff, because ntpq's mode 6 protocol depends on
reassembly of a response from multiple packets, with all packets
retransmitted if any are lost.  In the face of packet loss, the rows
per request are dropped as low as 2, which would almost surely fit in
a single response packet (470 bytes or so).  Without packet loss, the
number of rows per request climbs as high as 96, chosen to fit in the
limit of 32 packets in one response.

mrulist takes up to three arguments filtering or sorting the list:

ntpq -c "mrulist mincount=2"

(who wants to see singletons where avgint is useless?)

ntpq -c "mrulist limited laddr="

(show only source addresses corresponding to packets addressed to my local address, further filtered by showing only those
addresses which exceeded rate limits with the last packet)

ntpq -c "mrulist sort=-avgint resany=0x400"
ntpq -c "mrulist sort=-avgint kod"

(these are equivalent and show addresses which triggered a KoD rate
limit response with their last packet, sorted by the average interval

ntpq -c "mrulist sort=-lstint"

(full list with reversed sort)

In addition to the official tarballs, there are Windows binaries (for
2000, XP, and later) on http://davehart.net/ntp/win/x86/

Dave Hart

More information about the questions mailing list