* plugin/cache: add prefer_positive stale policy
Add an opt-in serve_stale_policy that prefers an eligible success-cache
answer over denial-cache entries while serve_stale is enabled. Preserve the
existing ncache-first behavior when the policy is absent.
Also classify SOA-backed CNAME NODATA responses in the cache so incomplete
answers cannot be selected as positive stale responses.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 25da81ab-92dd-4663-b480-efd6262090c6
Signed-off-by: Nitin Nizhawan <nnizhawan@microsoft.com>
* plugin/cache: retain last-known-good positive answers
Keep an answering success-cache item reachable when a later NOERROR or
referral response overwrites the visible cache key without answering the
question. This lets prefer_positive survive empty responses, referrals, and
additional-only data while leaving policy-off lookup behavior unchanged.
Return the exact accepted verify refresh item instead of re-reading an
ambiguous cache key, avoiding expired TTL wraparound for uncacheable replies.
Add regression coverage for non-answer refreshes, NODATA, SERVFAIL, NOTIMP,
stale-window expiry, and bounded verify reply shaping.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 25da81ab-92dd-4663-b480-efd6262090c6
Signed-off-by: Nitin Nizhawan <nnizhawan@microsoft.com>
* plugin/cache: validate preferred stale answers
Reject truncated, DNSSEC-expired, mismatched-class, unrelated ANY, and ambiguous CNAME refreshes before replacing a stale last-known-good answer. Precompute answer eligibility when cache items are created so prefer_positive hits avoid repeated CNAME walks.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 25da81ab-92dd-4663-b480-efd6262090c6
Signed-off-by: Nitin Nizhawan <nnizhawan@microsoft.com>
---------
Signed-off-by: Nitin Nizhawan <nnizhawan@microsoft.com>
Co-authored-by: Nitin Nizhawan <nnizhawan@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 25da81ab-92dd-4663-b480-efd6262090c6
Keep cache timestamps and TTL calculations on the time values returned by the cache clock. Converting them with UTC strips Go's monotonic clock reading and can extend cached entries when the wall clock moves backward.
Add a regression test that verifies new cache items retain the original monotonic timestamp.
Fixes#5478.
Signed-off-by: houyuwushang <liuluoqianqiu@outlook.com>
This commit removes superfluous allocations of the Answer, Ns, and Extra
slices when copying a cached a dns.Msg. The allocations are superfluous
because we immediately overwrite the newly copied slices with
filterRRSlice. It also updates filterRRSlice to pre-calculate the size
of the slice being copied into.
Benchmark results:
goos: darwin
goarch: arm64
pkg: github.com/coredns/coredns/plugin/cache
cpu: Apple M4 Pro
│ base.10.txt │ new.10.txt │
│ sec/op │ sec/op vs base │
CacheResponse-14 471.1n ± 0% 462.9n ± 2% -1.74% (p=0.009 n=10)
│ base.10.txt │ new.10.txt │
│ B/op │ B/op vs base │
CacheResponse-14 672.0 ± 0% 656.0 ± 0% -2.38% (p=0.000 n=10)
│ base.10.txt │ new.10.txt │
│ allocs/op │ allocs/op vs base │
CacheResponse-14 13.00 ± 0% 12.00 ± 0% -7.69% (p=0.000 n=10)
Signed-off-by: Charlie Vieth <charlie.vieth@gmail.com>
For responses synthesized by known wildcard records, publish metadata containing the wildcard record name
Signed-off-by: Chris O'Haver <cohaver@infoblox.com>
The filtering of DNSSEC records in the cache plugin was not done
correctly. Also the change to introduced this bug didn't take into
account that the cache - by virtue of differentiating between DNSSEC and
no-DNSSEC - relied on not copying the data from the cache.
This change copies and then filters the data and factors the filtering
into a function that is used in two places (albeit with on ugly boolean
parameters to prevent copying things twice).
Add tests, do_test.go is moved to test/cache_test.go because the OPT
handing is done outside of the cache plugin. The core server re-attaches
the correct OPT when replying, so that makes for a better e2e test.
Added small unit test for filterRRslice and an explicit test that asks
for DNSSEC first and then plain, and vice versa to test cache behavior.
Fixes: #4146
Signed-off-by: Miek Gieben <miek@miek.nl>
* cache: default to DNSSEC
This change does away with the DNS/DNSSEC distinction the cache
currently makes. Cache will always make coredns perform a DNSSEC query
and store that result. If a client just needs plain DNS, the DNSSEC
records are stripped from the response.
It should also be more memory efficient, because we store a reply once
and not one DNS and another for DNSSEC.
Fixes: #3836
Signed-off-by: Miek Gieben <miek@miek.nl>
* Change OPT RR when one is present in the msg.
Signed-off-by: Miek Gieben <miek@miek.nl>
* Fix comment for isDNSSEC
Signed-off-by: Miek Gieben <miek@miek.nl>
* Update plugin/cache/handler.go
Co-authored-by: Chris O'Haver <cohaver@infoblox.com>
* Update plugin/cache/item.go
Co-authored-by: Chris O'Haver <cohaver@infoblox.com>
* Code review; fix comment for isDNSSEC
Signed-off-by: Miek Gieben <miek@miek.nl>
* Update doc and set AD to false
Set Authenticated Data to false when DNSSEC was not wanted. Also update
the readme with the new behavior.
Signed-off-by: Miek Gieben <miek@miek.nl>
* Update plugin/cache/handler.go
Co-authored-by: Chris O'Haver <cohaver@infoblox.com>
Co-authored-by: Chris O'Haver <cohaver@infoblox.com>
* plugin/cache: remove item.Autoritative
Confuses clients if not set; remove it.
Signed-off-by: Miek Gieben <miek@miek.nl>
* Add extra comments on why we do this
Signed-off-by: Miek Gieben <miek@miek.nl>
* Fix max-age in http server
Move the minMsgTTL to dnsutil and rename it MinimalTTL, move some
constants there as well.
Use these new function in server_https to correctly set the max-age
HTTP header.
Fixes: #1823
* Linter
* Remove Compress by default
Set Compress = true in Scrub only when the message doesn not fit the
advertized buffer. Doing compression is expensive, so try to avoid it.
Master vs this branch
pkg: github.com/coredns/coredns/plugin/cache
BenchmarkCacheResponse-2 50000 24774 ns/op
pkg: github.com/coredns/coredns/plugin/cache
BenchmarkCacheResponse-2 100000 21960 ns/op
* and make it compile
* Revert "pkg/typify: empty messages are OtherError (#1531)"
This reverts commit fc1d73ffa9.
* plugin/cache: add failsafeTTL
If we can not see what TTL we should put on a message to be cached, use
5 seconds as minimal TTL. We used to apply the maximum TTL to these
messages.
* Improve plugin/cache metrics
* Add coredns_cache_prefetch_total metric to track number of prefetches.
* Remove unnecessary Cache.get() call which would incorrectly increment
cache counters.
* Initialize all counters and gauges at zero.
* Allow prefetching of a single request per ttl
The original implementation didn't allow prefetching queries which are
only requested once during the duration of a TTL. The minimum amount of
queries which had to be seen was therefore capped at 2.
This change also implements a real prefetch test. The existing test was
a noop and always passed regardless of any prefetch implementation.
* Fix prefetching for items with a short TTL
The default prefetch threshold (percentage) is 10% of the lifetime of a
cache item. With the previous implementation, this disabled prefetching
for all items with a TTL < 10s (the resulting percentage would be 0, at
which point a cached item is already discarded).
This change uses a time based threshold calculation and ensures that
a prefetch is triggered at a TTL of 1 at the latest.
* Fix wrong duration reporting of cached responses
The logging and metrics plugins (among others) included the duration of
a cache prefetch in the request latency of client request. This change
fixes this wrong reporting and executes the prefetch request in a
goroutine in the background.
The cache plugin always returned a minimum TTL of 5 seconds, regardless
of the actual TTL of the records. A cache is not authoritative for the
record TTL and should not extend it.
* Rename middleware to plugin
first pass; mostly used 'sed', few spots where I manually changed
text.
This still builds a coredns binary.
* fmt error
* Rename AddMiddleware to AddPlugin
* Readd AddMiddleware to remain backwards compat