Documentation
¶
Index ¶
- Constants
- func AcquireMsg() *dns.Msg
- func ReleaseMsg(m *dns.Msg)
- func SetCacheSizeFuncs(positive, negative func() int, extras ...func() int)
- func SetMetricsInstance(m *CacheMetrics)
- func UpdateCacheSizeMetrics()
- type Cache
- func (c *Cache) ForEachEntry(fn func(positive bool, key uint64, entry *CacheEntry) bool)
- func (c *Cache) InlineBarrier() bool
- func (c *Cache) Name() string
- func (c *Cache) Purge(q dns.Question)
- func (c *Cache) ServeDNS(ctx context.Context, ch *middleware.Chain)
- func (c *Cache) Set(key uint64, msg *dns.Msg)
- func (c *Cache) SetDNSSECCryptoLimiter(limiter middleware.DNSSECCryptoLimiter)
- func (c *Cache) SetPrefetchQueryer(q middleware.Queryer)
- func (c *Cache) SetQueryer(q middleware.Queryer)
- func (c *Cache) SetSidecarPolicy(p middleware.SidecarPolicyProvider)
- func (c *Cache) Stats() map[string]any
- func (c *Cache) Stop()
- func (c *Cache) Store() middleware.Store
- type CacheConfig
- type CacheEntry
- func (e *CacheEntry) CompareAndStampSidecar(prev, next *middleware.Sidecar) bool
- func (e *CacheEntry) GetRateLimiter() *rate.Limiter
- func (e *CacheEntry) IsExpired() bool
- func (e *CacheEntry) PrefetchEligible() bool
- func (e *CacheEntry) ShouldPrefetch(threshold int) bool
- func (e *CacheEntry) Sidecar() *middleware.Sidecar
- func (e *CacheEntry) TTL() int
- func (e *CacheEntry) ToMsg(req *dns.Msg) *dns.Msg
- type CacheKey
- type CacheMetrics
- type DCache
- type FailureCache
- func (c *FailureCache) Len() int
- func (c *FailureCache) Lookup(key FailureQuestionKey) (FailureHit, bool)
- func (c *FailureCache) LookupWire(name []byte, qtype, qclass uint16, cd bool) (FailureHit, bool)
- func (c *FailureCache) PurgeQuestion(q dns.Question) int
- func (c *FailureCache) RecordQuestion(key FailureQuestionKey, provenance FailureProvenance, ...) FailureHit
- func (c *FailureCache) RecordZone(key FailureZoneKey, provenance FailureProvenance, witness []denialWitnessPair) FailureHit
- func (c *FailureCache) ResetMatching(key FailureQuestionKey) int
- func (c *FailureCache) ResetQuestion(key FailureQuestionKey) bool
- func (c *FailureCache) ResetZone(key FailureZoneKey) bool
- func (c *FailureCache) RetryKey(key FailureQuestionKey) (uint64, bool)
- func (c *FailureCache) Stop()
- type FailureCacheConfig
- type FailureHit
- type FailureKind
- type FailureProvenance
- type FailureQuestionKey
- type FailureZoneKey
- type NegativeCache
- type PositiveCache
- type PrefetchQueue
- type PrefetchRequest
- type ResponseWriter
- type Store
- func (s *Store) ClearZoneFailure(q dns.Question, zone string)
- func (s *Store) DenialMissHoldsWire(name []byte, qclass uint16, hit FailureHit) bool
- func (s *Store) DenialProofBytes() int64
- func (s *Store) DenialProofLen() int
- func (s *Store) DenialProofZones() int
- func (s *Store) FailureLen() int
- func (s *Store) FailureRetryKey(req *dns.Msg, scope netip.Prefix) (uint64, bool)
- func (s *Store) ForEach(fn func(positive bool, key uint64, entry *CacheEntry) bool)
- func (s *Store) Get(req *dns.Msg) (*dns.Msg, bool)
- func (s *Store) GetWithContext(ctx context.Context, req *dns.Msg) (*dns.Msg, bool)
- func (s *Store) Lookup(req *dns.Msg) (*CacheEntry, bool)
- func (s *Store) LookupByKey(key uint64) (*CacheEntry, bool)
- func (s *Store) LookupByKeyVerified(key uint64, want CacheKey) (*CacheEntry, bool)
- func (s *Store) LookupDenialProof(req *dns.Msg, work dnssec.NSEC3Work) (*dns.Msg, middleware.ValidatedNegativeProofKind, string, bool)
- func (s *Store) LookupFailure(req *dns.Msg, scope netip.Prefix) (FailureHit, bool)
- func (s *Store) LookupFailureWire(name []byte, qtype, qclass uint16, cd bool) (FailureHit, bool)
- func (s *Store) LookupNXDomainCut(req *dns.Msg) (*nxDomainCutEntry, bool)
- func (s *Store) LookupNXDomainCutWire(name []byte, qclass uint16) (*nxDomainCutEntry, bool)
- func (s *Store) NXDomainCutLen() int
- func (s *Store) NegativeLen() int
- func (s *Store) PositiveLen() int
- func (s *Store) Purge(q dns.Question)
- func (s *Store) RecordDenialProof(proof *dns.Msg, zone string, kind middleware.ValidatedNegativeProofKind, ...) bool
- func (s *Store) RecordFailure(req *dns.Msg, scope netip.Prefix, provenance FailureProvenance, ...)
- func (s *Store) RecordNXDomainCut(proof *dns.Msg, deniedName string, zone string, cutUntil time.Time) bool
- func (s *Store) RecordZoneFailure(q dns.Question, zone string)
- func (s *Store) ReplaceIfCurrent(key uint64, expected *CacheEntry, resp *dns.Msg, cutUntil time.Time, ...) bool
- func (s *Store) SetEntryWithKey(key uint64, entry *CacheEntry, mt dnsutil.ResponseType)
- func (s *Store) SetFromResponse(resp *dns.Msg, keyCD bool, cutUntil time.Time)
- func (s *Store) SetFromResponseScoped(key uint64, resp *dns.Msg, scope netip.Prefix, cutUntil time.Time, ...)
- func (s *Store) SetFromResponseWithCut(resp *dns.Msg, keyCD bool, cutUntil time.Time, cutKey uint64)
- func (s *Store) SetFromResponseWithKey(key uint64, resp *dns.Msg, cutUntil time.Time, cutKey uint64)
- func (s *Store) SetSidecarEvaluator(ev middleware.SidecarEvaluator)
- func (s *Store) Stop()
- type TTLManager
Constants ¶
const ( // DefaultFailureCacheSize bounds retained exact and zone failure states. DefaultFailureCacheSize = 4096 // DefaultFailureInitialTTL is the first cached-failure backoff interval. DefaultFailureInitialTTL = 5 * time.Second // DefaultFailureMaxTTL caps cached-failure backoff. DefaultFailureMaxTTL = 5 * time.Minute )
Variables ¶
This section is empty.
Functions ¶
func AcquireMsg ¶ added in v1.0.0
AcquireMsg returns an empty msg from pool with pre-allocated slices.
func SetCacheSizeFuncs ¶ added in v1.6.1
SetCacheSizeFuncs sets the functions to get cache sizes. Optional functions preserve the original two-argument source contract: extras[0] is the RFC 9520 failure cache, extras[1] the RFC 8020 cut index, and extras[2] the RFC 8198 proof index.
func SetMetricsInstance ¶ added in v1.6.1
func SetMetricsInstance(m *CacheMetrics)
SetMetricsInstance sets the metrics instance for hit rate calculation
func UpdateCacheSizeMetrics ¶ added in v1.6.1
func UpdateCacheSizeMetrics()
UpdateCacheSizeMetrics updates the cache size gauges
Types ¶
type Cache ¶
type Cache struct {
// contains filtered or unexported fields
}
Cache is the cache implementation.
func (*Cache) ForEachEntry ¶ added in v1.6.2
func (c *Cache) ForEachEntry(fn func(positive bool, key uint64, entry *CacheEntry) bool)
ForEachEntry iterates over positive and negative cache entries. Iteration is not atomic with concurrent updates. Returning false from fn stops iteration.
func (*Cache) InlineBarrier ¶ added in v1.8.0
InlineBarrier declares that the cache honors Chain.InlineOnly: an inline pass gets the wire ladder and nothing below it — everything past the ladder can materialize, wait, or resolve, and a transport reader can afford none of those. Its presence is what lets the server turn the reader fast path on at all.
func (*Cache) Purge ¶ added in v1.6.4
(*Cache).Purge removes positive and negative cache entries for q under both CD=true and CD=false. Implements middleware.Purger so the api purge endpoint can invalidate cache state without synthesising a CHAOS-NULL request.
func (*Cache) ServeDNS ¶
func (c *Cache) ServeDNS(ctx context.Context, ch *middleware.Chain)
(*Cache).ServeDNS serveDNS implements the middleware.Handler interface. A wire-born request first tries the wire fast path — the exact-entry lookup on the wire question through the canonical key, served through the writer lease without a decoded request. Everything else — misses, composite candidates (NXDOMAIN cut, aggressive denial, failure cache), scoped/ECS traffic, prefetch-due entries, Msg-path-only hit shapes — falls through to materialization and the ordinary body with every gate and lookup it has today.
func (*Cache) Set ¶
(*Cache).Set adds a new element to the cache. It is retained for source compatibility with prefetch and plugin callers. Ordinary answers honor the supplied answer-cache key. SERVFAIL uses its full DNS Question instead: shared RFC 9520 state verifies the complete key preimage and cannot safely accept an opaque hash as its identity.
Internally the entry is constructed with origTTL adjusted to the real upstream TTL so subsequent prefetch decisions don't miscalculate from the post-Calculate (clamped) value.
func (*Cache) SetDNSSECCryptoLimiter ¶ added in v1.7.4
func (c *Cache) SetDNSSECCryptoLimiter(limiter middleware.DNSSECCryptoLimiter)
SetDNSSECCryptoLimiter installs the resolver-owned gate used by optional NSEC3 proof lookups. Called once by middleware.Setup before publication.
func (*Cache) SetPrefetchQueryer ¶ added in v1.6.4
func (c *Cache) SetPrefetchQueryer(q middleware.Queryer)
(*Cache).SetPrefetchQueryer installs the Queryer used by the prefetch worker. The prefetch sub-pipeline excludes the cache middleware so a refresh reaches the upstream resolver / forwarder instead of returning its own about-to-expire entry.
func (*Cache) SetQueryer ¶ added in v1.6.4
func (c *Cache) SetQueryer(q middleware.Queryer)
(*Cache).SetQueryer installs the Queryer used for internal client-shaped work (CNAME chase on cache writeback, future DNAME target lookup from the resolver). Called once from sdns.go startup.
func (*Cache) SetSidecarPolicy ¶ added in v1.8.2
func (c *Cache) SetSidecarPolicy(p middleware.SidecarPolicyProvider)
SetSidecarPolicy wires both halves of the sidecar seam (middleware.SidecarPolicySetter, injected by Setup before the pipeline publishes): the evaluator stamps entries at every admission door, the gate judges record-bearing byte serves.
func (*Cache) Stop ¶ added in v1.5.0
func (c *Cache) Stop()
(*Cache).Stop stop gracefully shuts down the cache.
func (*Cache) Store ¶ added in v1.6.4
func (c *Cache) Store() middleware.Store
(*Cache).Store returns the storage facade, typed as middleware.Store so Cache satisfies middleware.StoreProvider for auto-wiring in middleware.Setup. External callers that need the full *Store surface can type-assert.
type CacheConfig ¶ added in v1.5.0
type CacheConfig struct {
Size int
Prefetch int
PositiveTTL time.Duration
NegativeTTL time.Duration
MinTTL time.Duration
MaxTTL time.Duration
RateLimit int
ServeStale bool
// ServeStaleMaxTTL is measured from the admitted answer TTL's expiry.
// Zero leaves cutUntil as the only stale lifetime bound.
ServeStaleMaxTTL time.Duration
// ECSMaxTTL caps the lifetime of cache entries keyed under an
// ECS scope. Geo-routed answers tend to go stale faster than
// the resolver's general MaxTTL would suggest — a CDN
// re-pointing a /24 between PoPs is normal traffic. Zero
// disables the cap (scoped entries live as long as their
// upstream TTL allowed). Populated from cfg.ECS.CacheLimitTTL.
ECSMaxTTL time.Duration
}
CacheConfig holds cache configuration with validation.
func (CacheConfig) Validate ¶ added in v1.5.0
func (cc CacheConfig) Validate() error
(CacheConfig).Validate validate checks if the configuration is valid.
type CacheEntry ¶ added in v1.5.0
type CacheEntry struct {
// contains filtered or unexported fields
}
CacheEntry represents an immutable cache entry.
The response is retained in packed wire form: one pointer-free byte slice instead of a parsed message graph of ~two dozen heap objects. At the field scale that graph was the dominant GC mark cost (18M live objects on a warm 743k-entry canary). Serving unpacks a fresh message per hit — comparable work to the deep Copy the parsed representation already paid, since a served message must be privately mutable either way.
func NewCacheEntry ¶ added in v1.5.0
NewCacheEntry creates a new cache entry from a DNS message.
func NewCacheEntryWithKey ¶ added in v1.6.0
NewCacheEntryWithKey creates a new cache entry with a specific key for rate limiting. A message that cannot be packed returns nil — such a response was never servable on the wire, so declining to cache it is the safe outcome.
func NewScopedCacheEntry ¶ added in v1.7.0
func NewScopedCacheEntry(msg *dns.Msg, ttl time.Duration, rateLimit int, scope netip.Prefix) *CacheEntry
NewScopedCacheEntry creates a cache entry that's been keyed under an ECS scope. scope MUST be the prefix the entry's key was computed from — the hit-path verifier compares the two exactly, so an entry admitted under a scope it does not carry is unreachable. A /0 or invalid scope leaves the entry shared, matching CacheKey.Hash, which collapses /0 to the unscoped key.
func (*CacheEntry) CompareAndStampSidecar ¶ added in v1.8.2
func (e *CacheEntry) CompareAndStampSidecar(prev, next *middleware.Sidecar) bool
CompareAndStampSidecar installs next if the entry still carries prev — the restamp a serve performs when it finds a stale generation. The generation lives inside the opaque value; the CAS only guarantees no concurrent restamp is silently overwritten.
func (*CacheEntry) GetRateLimiter ¶ added in v1.6.0
func (e *CacheEntry) GetRateLimiter() *rate.Limiter
(*CacheEntry).GetRateLimiter returns the shared rate limiter for this entry
func (*CacheEntry) IsExpired ¶ added in v1.5.0
func (e *CacheEntry) IsExpired() bool
(*CacheEntry).IsExpired isExpired checks if the cache entry has expired.
func (*CacheEntry) PrefetchEligible ¶ added in v1.7.0
func (e *CacheEntry) PrefetchEligible() bool
PrefetchEligible reports whether the prefetch worker may refresh this entry. Scoped entries are skipped because the worker has no client IP, so a refresh would lose the ECS scope and create a shared-key entry instead — wrong answer for the wrong audience.
func (*CacheEntry) ShouldPrefetch ¶ added in v1.5.0
func (e *CacheEntry) ShouldPrefetch(threshold int) bool
(*CacheEntry).ShouldPrefetch shouldPrefetch checks if this entry should be prefetched.
func (*CacheEntry) Sidecar ¶ added in v1.8.2
func (e *CacheEntry) Sidecar() *middleware.Sidecar
Sidecar returns the entry's stamped policy state; nil means the entry was never evaluated.
func (*CacheEntry) TTL ¶ added in v1.5.0
func (e *CacheEntry) TTL() int
(*CacheEntry).TTL TTL returns the remaining TTL in seconds.
type CacheKey ¶ added in v1.5.0
CacheKey represents a structured cache key.
Scope is the ECS prefix (RFC 7871) the authority claimed its answer is scoped to. The zero value means "shared" — an entry keyed with no scope is reachable by any client, which is the pre-Stage-2 default and how non-ECS traffic and SCOPE=0 authority answers continue to behave after the upgrade.
func (CacheKey) Hash ¶ added in v1.5.0
(CacheKey).Hash returns the cache key hash. Routes to cache.KeyWithPrefix when Scope is valid (family + bit-length + address are all folded in so /22 and /24 of the same address don't alias), and to the legacy cache.Key — bit-identical to pre-Stage-2 — when Scope is the zero value, so old entries keep hitting after upgrade. A /0 scope collapses to the unscoped key because a /0 answer is semantically "global", same as no scope.
type CacheMetrics ¶ added in v1.5.0
type CacheMetrics struct {
// contains filtered or unexported fields
}
CacheMetrics tracks cache performance metrics.
func (*CacheMetrics) Eviction ¶ added in v1.5.0
func (m *CacheMetrics) Eviction()
(*CacheMetrics).Eviction eviction records a cache eviction.
func (*CacheMetrics) Hit ¶ added in v1.5.0
func (m *CacheMetrics) Hit()
(*CacheMetrics).Hit hit records a cache hit.
func (*CacheMetrics) Miss ¶ added in v1.5.0
func (m *CacheMetrics) Miss()
(*CacheMetrics).Miss miss records a cache miss.
func (*CacheMetrics) Prefetch ¶ added in v1.5.0
func (m *CacheMetrics) Prefetch()
(*CacheMetrics).Prefetch prefetch records a prefetch operation.
func (*CacheMetrics) Stats ¶ added in v1.5.0
func (m *CacheMetrics) Stats() (hits, misses, evictions, prefetches int64)
(*CacheMetrics).Stats stats returns current metrics.
type DCache ¶ added in v1.6.4
type DCache interface {
Get(key uint64) (*CacheEntry, bool)
Set(key uint64, entry *CacheEntry)
Remove(key uint64)
Len() int
}
DCache defines the interface for DNS cache implementations.
type FailureCache ¶ added in v1.7.4
type FailureCache struct {
// contains filtered or unexported fields
}
FailureCache is a bounded, concurrent cache of recursive-resolution failures. Expired entries remain as backoff history but are not cache hits.
func NewFailureCache ¶ added in v1.7.4
func NewFailureCache(cfg FailureCacheConfig) (*FailureCache, error)
NewFailureCache constructs a bounded failure cache.
func (*FailureCache) Len ¶ added in v1.7.4
func (c *FailureCache) Len() int
Len returns the number of retained active and expired states.
func (*FailureCache) Lookup ¶ added in v1.7.4
func (c *FailureCache) Lookup(key FailureQuestionKey) (FailureHit, bool)
Lookup returns an active exact failure, or otherwise the closest active ancestor-zone failure. Expired state is retained for Record and RetryKey but never returned as a hit.
func (*FailureCache) LookupWire ¶ added in v1.8.0
func (c *FailureCache) LookupWire(name []byte, qtype, qclass uint16, cd bool) (FailureHit, bool)
LookupWire is Lookup for a wire-born question without an ECS scope: the same exact-question probe and ancestor-zone walk, keyed through the canonical wire hashes (bit-identical to the presentation ones) and verified by fold comparison — no strings, no allocation. Scoped entries never match: the wire path carries no client scope, and scope is part of both the hash and the verification.
func (*FailureCache) PurgeQuestion ¶ added in v1.7.4
func (c *FailureCache) PurgeQuestion(q dns.Question) int
PurgeQuestion removes every CD/ECS variant of an exact question and a zone-wide state whose owner is the purged name. Purge is an explicit, infrequent operator action, so a bounded O(n) scan avoids maintaining a second attacker-influenced index.
func (*FailureCache) RecordQuestion ¶ added in v1.7.4
func (c *FailureCache) RecordQuestion(key FailureQuestionKey, provenance FailureProvenance, witness []denialWitnessPair) FailureHit
RecordQuestion records an exact failure. Repeated calls during an active generation are idempotent. After expiry, concurrent recorders advance the streak exactly once.
func (*FailureCache) RecordZone ¶ added in v1.7.4
func (c *FailureCache) RecordZone(key FailureZoneKey, provenance FailureProvenance, witness []denialWitnessPair) FailureHit
RecordZone records a zone-wide reachability failure. Repeated calls during an active generation are idempotent. Zone failures are not partitioned by CD or ECS because authority transport reachability is shared.
func (*FailureCache) ResetMatching ¶ added in v1.7.4
func (c *FailureCache) ResetMatching(key FailureQuestionKey) int
ResetMatching removes exact history and every ancestor-zone history covered by a fresh useful response. Recovery deliberately deletes the streak: RFC 9520 backoff applies to persistent failures, so a later independent failure starts a new episode at the initial interval. Retaining an expired streak here would also keep healthy descendants in the retry-generation path. It returns the number of states deleted.
func (*FailureCache) ResetQuestion ¶ added in v1.7.4
func (c *FailureCache) ResetQuestion(key FailureQuestionKey) bool
ResetQuestion deletes exact history when the full key still matches.
func (*FailureCache) ResetZone ¶ added in v1.7.4
func (c *FailureCache) ResetZone(key FailureZoneKey) bool
ResetZone deletes zone history when the full key still matches.
func (*FailureCache) RetryKey ¶ added in v1.7.4
func (c *FailureCache) RetryKey(key FailureQuestionKey) (uint64, bool)
RetryKey returns a stable singleflight key for a matching expired failure generation. An active exact or ancestor-zone state returns false because it should be consumed through Lookup instead. Closest-zone history takes precedence over exact history so different random QNAMEs below a failed authority converge on one probe generation.
func (*FailureCache) Stop ¶ added in v1.7.4
func (c *FailureCache) Stop()
Stop releases resources owned by the backing cache.
type FailureCacheConfig ¶ added in v1.7.4
type FailureCacheConfig struct {
Size int
InitialTTL time.Duration
MaxTTL time.Duration
Now func() time.Time
}
FailureCacheConfig configures the bounded failure cache. Zero TTL values use DefaultFailureInitialTTL and DefaultFailureMaxTTL. Now is injectable for deterministic tests; nil uses time.Now.
type FailureHit ¶ added in v1.7.4
type FailureHit struct {
Kind FailureKind
Provenance FailureProvenance
Streak uint32
RetryAfter time.Time
Question FailureQuestionKey
Zone FailureZoneKey
// contains filtered or unexported fields
}
FailureHit is an immutable snapshot of an active cached failure.
type FailureKind ¶ added in v1.7.4
type FailureKind uint8
FailureKind identifies whether a hit is question-specific or zone-wide.
const ( // FailureKindQuestion is an exact QNAME/QTYPE/QCLASS+CD+ECS failure. FailureKindQuestion FailureKind = iota + 1 // FailureKindZone is an authority-zone reachability failure. FailureKindZone )
type FailureProvenance ¶ added in v1.7.4
type FailureProvenance string
FailureProvenance identifies the failure class that admitted an entry. Admission policy belongs to the caller; the cache only retains the value for observability and for consumers that need to distinguish failure sources.
type FailureQuestionKey ¶ added in v1.7.4
FailureQuestionKey isolates failures by the complete DNS question, CD bit, and ECS audience. Invalid and /0 scopes are the shared global audience.
type FailureZoneKey ¶ added in v1.7.4
FailureZoneKey identifies a zone-wide reachability failure. Transport reachability is independent of the client's CD bit and ECS audience.
type NegativeCache ¶ added in v1.5.0
type NegativeCache struct {
// contains filtered or unexported fields
}
NegativeCache handles error DNS responses.
func NewNegativeCache ¶ added in v1.5.0
func NewNegativeCache(size int, minTTL, maxTTL time.Duration, metrics *CacheMetrics) *NegativeCache
NewNegativeCache creates a new negative cache.
func (*NegativeCache) Get ¶ added in v1.5.0
func (nc *NegativeCache) Get(key uint64) (*CacheEntry, bool)
(*NegativeCache).Get get retrieves an entry from the negative cache. Hit/Miss metrics are NOT recorded here — see PositiveCache.Get.
func (*NegativeCache) Len ¶ added in v1.5.0
func (nc *NegativeCache) Len() int
(*NegativeCache).Len len returns the number of entries in the cache.
func (*NegativeCache) Remove ¶ added in v1.5.0
func (nc *NegativeCache) Remove(key uint64)
(*NegativeCache).Remove remove deletes an entry from the negative cache.
func (*NegativeCache) Set ¶ added in v1.5.0
func (nc *NegativeCache) Set(key uint64, entry *CacheEntry)
(*NegativeCache).Set set stores an entry in the negative cache.
type PositiveCache ¶ added in v1.5.0
type PositiveCache struct {
// contains filtered or unexported fields
}
PositiveCache handles successful DNS responses.
func NewPositiveCache ¶ added in v1.5.0
func NewPositiveCache(size int, minTTL, maxTTL time.Duration, metrics *CacheMetrics) *PositiveCache
NewPositiveCache creates a new positive cache.
func (*PositiveCache) Get ¶ added in v1.5.0
func (pc *PositiveCache) Get(key uint64) (*CacheEntry, bool)
(*PositiveCache).Get get retrieves an entry from the positive cache. Hit/Miss metrics are NOT recorded here — checkCache consults both positive and negative caches per request and records the aggregate result once, so pushing metrics in here would double-count both sides of a single miss.
func (*PositiveCache) Len ¶ added in v1.5.0
func (pc *PositiveCache) Len() int
(*PositiveCache).Len len returns the number of entries in the cache.
func (*PositiveCache) Remove ¶ added in v1.5.0
func (pc *PositiveCache) Remove(key uint64)
(*PositiveCache).Remove remove deletes an entry from the positive cache.
func (*PositiveCache) Set ¶ added in v1.5.0
func (pc *PositiveCache) Set(key uint64, entry *CacheEntry)
(*PositiveCache).Set set stores an entry in the positive cache.
type PrefetchQueue ¶ added in v1.5.0
type PrefetchQueue struct {
// contains filtered or unexported fields
}
PrefetchQueue manages prefetch requests with worker pool.
func NewPrefetchQueue ¶ added in v1.5.0
func NewPrefetchQueue(workers, queueSize int, metrics *CacheMetrics) *PrefetchQueue
NewPrefetchQueue creates a new prefetch queue.
func (*PrefetchQueue) Add ¶ added in v1.5.0
func (pq *PrefetchQueue) Add(req PrefetchRequest) bool
(*PrefetchQueue).Add add queues a prefetch request.
func (*PrefetchQueue) Stop ¶ added in v1.5.0
func (pq *PrefetchQueue) Stop()
(*PrefetchQueue).Stop stop gracefully shuts down the prefetch queue.
type PrefetchRequest ¶ added in v1.5.0
type PrefetchRequest struct {
Request *dns.Msg
Key uint64
Cache *Cache // Reference to the cache to store prefetched results
Entry *CacheEntry // Entry that claimed the prefetch; used to release the claim on failure/drop
RequestHadECS bool // Original client ECS, retained after EDNS policy stripping
}
PrefetchRequest represents a DNS query to be prefetched.
type ResponseWriter ¶
type ResponseWriter struct {
middleware.ResponseWriter
// contains filtered or unexported fields
}
ResponseWriter is the response writer for cache.
type Store ¶ added in v1.6.4
type Store struct {
// contains filtered or unexported fields
}
Store is the cache backing for the cache middleware. The answer and failure sub-caches are constructed by Cache.New and shared with Store; Store owns the separately bounded RFC 8020 cut index. It centralises classification, keying, and TTL handling so callers outside ServeDNS (resolver sub-queries, queryer-driven prefetch, future API purge wiring) don't need to understand the wire-write rules in ResponseWriter.WriteMsg.
SetFromResponse keys on the caller-supplied keyCD rather than on resp.CheckingDisabled to make the keying contract explicit at every call site — Forwarder and Resolver both temporarily mutate CD on the upstream request, and silent reliance on resp.CheckingDisabled is the kind of thing that splits CD=1 and CD=0 lookups across stale entries when a future change forgets to restore.
func NewStore ¶ added in v1.6.4
func NewStore(positive *PositiveCache, negative *NegativeCache, cfg CacheConfig, failures ...*FailureCache) *Store
NewStore returns a Store backed by the supplied sub-caches. The caches are shared with the surrounding *Cache; this constructor does not allocate them.
func (*Store) ClearZoneFailure ¶ added in v1.7.4
ClearZoneFailure removes authority reachability history after the resolver receives a useful response from that same zone. Local/static cache writers never call this, so a hosts-file answer cannot falsely mark an upstream zone as recovered.
func (*Store) DenialMissHoldsWire ¶ added in v1.8.0
func (s *Store) DenialMissHoldsWire(name []byte, qclass uint16, hit FailureHit) bool
DenialMissHoldsWire reports whether a failure entry's record-time proof that aggressive denial does not apply is still valid for this wire-born name — the condition under which the wire path may serve the failure without materializing.
func (*Store) DenialProofBytes ¶ added in v1.7.4
DenialProofBytes returns the retained DNS wire bytes.
func (*Store) DenialProofLen ¶ added in v1.7.4
DenialProofLen returns retained SOA and denial RRset entries.
func (*Store) DenialProofZones ¶ added in v1.7.4
DenialProofZones returns the number of signer-zone shards.
func (*Store) FailureLen ¶ added in v1.7.4
FailureLen returns retained active and expired RFC 9520 failure states.
func (*Store) FailureRetryKey ¶ added in v1.7.4
FailureRetryKey returns the retained failure generation used to coalesce the first retry after a backoff expires. Different random QNAMEs below the same failed zone therefore elect only one probe leader.
func (*Store) ForEach ¶ added in v1.6.4
func (s *Store) ForEach(fn func(positive bool, key uint64, entry *CacheEntry) bool)
ForEach iterates over positive then negative entries. Returning false from fn stops iteration. Iteration is not atomic with concurrent updates.
func (*Store) Get ¶ added in v1.6.4
Get returns a materialised cached response for req. Reply header/ID/CD/AD interaction is handled by CacheEntry.ToMsg, which needs req for SetReply.
func (*Store) GetWithContext ¶ added in v1.7.4
GetWithContext is Get with request-tree policy and NSEC3 memo propagation. Resolver-private DS/DNSKEY lookups manufacture fresh messages, so the context marker is what preserves an outer client's CD/ECS isolation.
func (*Store) Lookup ¶ added in v1.6.4
func (s *Store) Lookup(req *dns.Msg) (*CacheEntry, bool)
Lookup returns the cache entry for req without materialising a response. Used by callers that need to inspect TTL or prefetch flags before deciding whether to consume the entry.
func (*Store) LookupByKey ¶ added in v1.6.4
func (s *Store) LookupByKey(key uint64) (*CacheEntry, bool)
LookupByKey is the pre-keyed form of Lookup, used by hot paths inside the cache middleware that already computed the key.
Callers MUST verify the returned entry against the preimage they keyed with (use LookupByKeyVerified, or entryMatchesKey / entryMatchesWire): the map key is a non-cryptographic 64-bit xxhash of that preimage, so a hash collision would otherwise serve one query's answer to another.
func (*Store) LookupByKeyVerified ¶ added in v1.7.1
func (s *Store) LookupByKeyVerified(key uint64, want CacheKey) (*CacheEntry, bool)
LookupByKeyVerified is LookupByKey plus a full-key check: it confirms the stored entry was admitted under exactly the preimage want describes before returning it. Without this, two distinct preimages that collide under xxhash64 would silently serve each other's answers — and because qnames are attacker-chosen, a collision can be searched for offline and used to poison the cache.
func (*Store) LookupDenialProof ¶ added in v1.7.4
func (s *Store) LookupDenialProof( req *dns.Msg, work dnssec.NSEC3Work, ) (*dns.Msg, middleware.ValidatedNegativeProofKind, string, bool)
LookupDenialProof evaluates the bounded RFC 8198 proof index for req. The returned kind and signer zone describe the exact proof family selected by the evaluator, including when a DO=0 response omits DNSSEC records.
func (*Store) LookupFailure ¶ added in v1.7.4
LookupFailure returns an active exact or closest-ancestor RFC 9520 failure.
func (*Store) LookupFailureWire ¶ added in v1.8.0
LookupFailureWire is LookupFailure for a wire-born question without an ECS scope.
func (*Store) LookupNXDomainCut ¶ added in v1.7.4
LookupNXDomainCut returns the closest locally validated RFC 8020 cut that covers req. CD=1 is always a miss: checking-disabled clients explicitly bypass locally synthesized authenticated denial state.
func (*Store) LookupNXDomainCutWire ¶ added in v1.8.0
LookupNXDomainCutWire is LookupNXDomainCut for a wire-born question: same store, same walk, no decoded message. CD gating is the caller's — the wire path mirrors the Msg entry's bypass conditions inline.
func (*Store) NXDomainCutLen ¶ added in v1.7.4
NXDomainCutLen returns retained locally validated RFC 8020 cuts.
func (*Store) NegativeLen ¶ added in v1.6.4
NegativeLen returns the number of entries in the negative cache.
func (*Store) PositiveLen ¶ added in v1.6.4
PositiveLen returns the number of entries in the positive cache.
func (*Store) Purge ¶ added in v1.6.4
Purge removes both CD=true and CD=false entries for q from positive and negative caches, including ECS-scoped entries.
Scoped entries don't have a deterministic key the caller could reproduce without enumerating every (qname, scope) the cache has ever seen — there's no per-qname index. We sweep them with ForEach: collect matching keys in one pass (snapshotting the per-segment locks individually), then Remove outside the iteration to avoid mutate-during-iterate hazards.
O(n) on the cache size; Purge is rare (explicit operator API call) so the linear scan is acceptable. If purge becomes hot, a per-qname index would lift this back to O(matches).
func (*Store) RecordDenialProof ¶ added in v1.7.4
func (s *Store) RecordDenialProof( proof *dns.Msg, zone string, kind middleware.ValidatedNegativeProofKind, cutUntil time.Time, ) bool
RecordDenialProof stores complete signed SOA and NSEC/NSEC3 RRsets from an exact locally validated terminal proof. kind is checked against the retained mechanism so provenance cannot be reinterpreted by a later cache layer.
func (*Store) RecordFailure ¶ added in v1.7.4
func (s *Store) RecordFailure(req *dns.Msg, scope netip.Prefix, provenance FailureProvenance, witness []denialWitnessPair)
RecordFailure records a question-specific terminal resolution failure. witness must be the miss witness captured at the moment the recording request's denial rung ran and missed (Cache.ServeDNS stashes it on the response writer), and nil from every path that never ran the rung — a CD or client-ECS tree that bypassed it, a compatibility Set, a scoped insert. A witness fabricated later would assert a miss nobody established at a moment nobody checked.
func (*Store) RecordNXDomainCut ¶ added in v1.7.4
func (s *Store) RecordNXDomainCut( proof *dns.Msg, deniedName string, zone string, cutUntil time.Time, ) bool
RecordNXDomainCut stores a locally validated terminal NXDOMAIN proof. deniedName is the exact authoritative query cycle that returned NXDOMAIN; it must never be inferred from the SOA owner.
func (*Store) RecordZoneFailure ¶ added in v1.7.4
RecordZoneFailure implements middleware.ResolutionFailureStore. Zone-wide reachability failures are deliberately independent of CD and ECS.
func (*Store) ReplaceIfCurrent ¶ added in v1.7.3
func (s *Store) ReplaceIfCurrent(key uint64, expected *CacheEntry, resp *dns.Msg, cutUntil time.Time, cutKey uint64) bool
ReplaceIfCurrent stores resp under key only if expected is still the live entry for that key — the pointer-CAS late-write guard for asynchronous refreshes (GHSA-mqfw-f48p-2vc8). A prefetch captures the entry that claimed it; by the time its refresh returns, newer state (a withdrawal NXDOMAIN, a re-delegated answer) may have replaced that entry, and the stale result must be dropped, not stored. Returns whether the replacement happened.
Two deliberate asymmetries:
- A SERVFAIL refresh never displaces a positive entry: it only CASes into the negative cache, so a transient upstream failure can't evict a still-valid answer. Production Cache SERVFAILs use FailureCache; this branch preserves the exported Store/NegativeCache contract for programmatic callers and manually seeded legacy entries.
- The CAS stays within one sub-cache. A negative entry refreshing to a positive answer is dropped rather than promoted — the two caches can't be swapped atomically, and the negative entry's short TTL re-resolves naturally.
func (*Store) SetEntryWithKey ¶ added in v1.6.4
func (s *Store) SetEntryWithKey(key uint64, entry *CacheEntry, mt dnsutil.ResponseType)
SetEntryWithKey replaces a stored entry directly. Used by Cache.Set's compatibility path where a caller already constructed the CacheEntry (e.g. prefetch worker writing back a response with adjusted origTTL).
func (*Store) SetFromResponse ¶ added in v1.6.4
SetFromResponse classifies resp (answer / NXDOMAIN+NODATA / resolution failure) and stores it under (resp.Question[0], keyCD). CHAOS signalling responses are skipped, matching ResponseWriter.WriteMsg. cutUntil bounds the entry to the delegation cut that produced it; zero means unbounded. This compatibility entry point has no lineage identity.
func (*Store) SetFromResponseScoped ¶ added in v1.7.0
func (s *Store) SetFromResponseScoped(key uint64, resp *dns.Msg, scope netip.Prefix, cutUntil time.Time, cutKey uint64)
SetFromResponseScoped is SetFromResponseWithKey for entries that were keyed under an ECS scope (RFC 7871 §7.1.2). scope must be the prefix key was computed from: the entry carries it, and the hit-path verifier compares the two so a colliding key cannot cross ECS audiences. The entry's PrefetchEligible is false — the prefetch worker has no client IP to derive ECS from, so refreshing a scoped entry would lose its scope and store the wrong-audience answer.
func (*Store) SetFromResponseWithCut ¶ added in v1.7.3
func (s *Store) SetFromResponseWithCut(resp *dns.Msg, keyCD bool, cutUntil time.Time, cutKey uint64)
SetFromResponseWithCut is SetFromResponse plus the delegation identity that supplied cutUntil, retained for the optional Phase-3 generation design.
func (*Store) SetFromResponseWithKey ¶ added in v1.6.4
func (s *Store) SetFromResponseWithKey(key uint64, resp *dns.Msg, cutUntil time.Time, cutKey uint64)
SetFromResponseWithKey is the pre-keyed form of SetFromResponse, used by ResponseWriter.WriteMsg, which has the key already.
func (*Store) SetSidecarEvaluator ¶ added in v1.8.2
func (s *Store) SetSidecarEvaluator(ev middleware.SidecarEvaluator)
SetSidecarEvaluator wires the admission half of the sidecar seam. Call before the store serves traffic; the field is not synchronized.
type TTLManager ¶ added in v1.5.0
type TTLManager struct {
// contains filtered or unexported fields
}
TTLManager manages TTL calculations.
func NewTTLManager ¶ added in v1.5.0
func NewTTLManager(min, max time.Duration) TTLManager
NewTTLManager creates a new TTL manager.
Source Files
¶
- cache.go
- denial_proof_cache.go
- denial_proof_witness.go
- denial_proof_work.go
- entry_wire.go
- entry_wire_chase.go
- failure_cache.go
- foreachentry.go
- negative_cache.go
- nxdomain_cut.go
- nxdomain_cut_wire.go
- positive_cache.go
- prefetch_queue.go
- prometheus.go
- serve_stale.go
- shared_ratelimiter.go
- store.go
- types.go
- wire_recompose.go