mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-07-04 01:07:49 +02:00
all: add flush cache domains config
This commit is contained in:
committed by
Cuong Manh Le
parent
34ebe9b054
commit
b50cccac85
@@ -1831,6 +1831,11 @@ func fieldErrorMsg(fe validator.FieldError) string {
|
|||||||
return fmt.Sprintf("must define at least %s element", fe.Param())
|
return fmt.Sprintf("must define at least %s element", fe.Param())
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("minimum value: %q", fe.Param())
|
return fmt.Sprintf("minimum value: %q", fe.Param())
|
||||||
|
case "max":
|
||||||
|
if fe.Kind() == reflect.Map || fe.Kind() == reflect.Slice {
|
||||||
|
return fmt.Sprintf("exceeded maximum number of elements: %s", fe.Param())
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("maximum value: %q", fe.Param())
|
||||||
case "len":
|
case "len":
|
||||||
if fe.Kind() == reflect.Slice {
|
if fe.Kind() == reflect.Slice {
|
||||||
return fmt.Sprintf("must have at least %s element", fe.Param())
|
return fmt.Sprintf("must have at least %s element", fe.Param())
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ func (p *prog) serveDNS(listenerNum string) error {
|
|||||||
go p.detectLoop(m)
|
go p.detectLoop(m)
|
||||||
q := m.Question[0]
|
q := m.Question[0]
|
||||||
domain := canonicalName(q.Name)
|
domain := canonicalName(q.Name)
|
||||||
|
if _, ok := p.cacheFlushDomainsMap[domain]; ok && p.cache != nil {
|
||||||
|
p.cache.Purge()
|
||||||
|
ctrld.Log(ctx, mainLog.Load().Debug(), "received query %q, local cache is purged", domain)
|
||||||
|
}
|
||||||
remoteIP, _, _ := net.SplitHostPort(w.RemoteAddr().String())
|
remoteIP, _, _ := net.SplitHostPort(w.RemoteAddr().String())
|
||||||
ci := p.getClientInfo(remoteIP, m)
|
ci := p.getClientInfo(remoteIP, m)
|
||||||
ci.ClientIDPref = p.cfg.Service.ClientIDPref
|
ci.ClientIDPref = p.cfg.Service.ClientIDPref
|
||||||
|
|||||||
+17
-11
@@ -70,17 +70,18 @@ type prog struct {
|
|||||||
logConn net.Conn
|
logConn net.Conn
|
||||||
cs *controlServer
|
cs *controlServer
|
||||||
|
|
||||||
cfg *ctrld.Config
|
cfg *ctrld.Config
|
||||||
localUpstreams []string
|
localUpstreams []string
|
||||||
ptrNameservers []string
|
ptrNameservers []string
|
||||||
appCallback *AppCallback
|
appCallback *AppCallback
|
||||||
cache dnscache.Cacher
|
cache dnscache.Cacher
|
||||||
sema semaphore
|
cacheFlushDomainsMap map[string]struct{}
|
||||||
ciTable *clientinfo.Table
|
sema semaphore
|
||||||
um *upstreamMonitor
|
ciTable *clientinfo.Table
|
||||||
router router.Router
|
um *upstreamMonitor
|
||||||
ptrLoopGuard *loopGuard
|
router router.Router
|
||||||
lanLoopGuard *loopGuard
|
ptrLoopGuard *loopGuard
|
||||||
|
lanLoopGuard *loopGuard
|
||||||
|
|
||||||
loopMu sync.Mutex
|
loopMu sync.Mutex
|
||||||
loop map[string]bool
|
loop map[string]bool
|
||||||
@@ -253,12 +254,17 @@ func (p *prog) run(reload bool, reloadCh chan struct{}) {
|
|||||||
p.loop = make(map[string]bool)
|
p.loop = make(map[string]bool)
|
||||||
p.lanLoopGuard = newLoopGuard()
|
p.lanLoopGuard = newLoopGuard()
|
||||||
p.ptrLoopGuard = newLoopGuard()
|
p.ptrLoopGuard = newLoopGuard()
|
||||||
|
p.cacheFlushDomainsMap = nil
|
||||||
if p.cfg.Service.CacheEnable {
|
if p.cfg.Service.CacheEnable {
|
||||||
cacher, err := dnscache.NewLRUCache(p.cfg.Service.CacheSize)
|
cacher, err := dnscache.NewLRUCache(p.cfg.Service.CacheSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to create cacher, caching is disabled")
|
mainLog.Load().Error().Err(err).Msg("failed to create cacher, caching is disabled")
|
||||||
} else {
|
} else {
|
||||||
p.cache = cacher
|
p.cache = cacher
|
||||||
|
p.cacheFlushDomainsMap = make(map[string]struct{}, 256)
|
||||||
|
for _, domain := range p.cfg.Service.CacheFlushDomains {
|
||||||
|
p.cacheFlushDomainsMap[canonicalName(domain)] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -179,26 +179,27 @@ func (c *Config) FirstUpstream() *UpstreamConfig {
|
|||||||
|
|
||||||
// ServiceConfig specifies the general ctrld config.
|
// ServiceConfig specifies the general ctrld config.
|
||||||
type ServiceConfig struct {
|
type ServiceConfig struct {
|
||||||
LogLevel string `mapstructure:"log_level" toml:"log_level,omitempty"`
|
LogLevel string `mapstructure:"log_level" toml:"log_level,omitempty"`
|
||||||
LogPath string `mapstructure:"log_path" toml:"log_path,omitempty"`
|
LogPath string `mapstructure:"log_path" toml:"log_path,omitempty"`
|
||||||
CacheEnable bool `mapstructure:"cache_enable" toml:"cache_enable,omitempty"`
|
CacheEnable bool `mapstructure:"cache_enable" toml:"cache_enable,omitempty"`
|
||||||
CacheSize int `mapstructure:"cache_size" toml:"cache_size,omitempty"`
|
CacheSize int `mapstructure:"cache_size" toml:"cache_size,omitempty"`
|
||||||
CacheTTLOverride int `mapstructure:"cache_ttl_override" toml:"cache_ttl_override,omitempty"`
|
CacheTTLOverride int `mapstructure:"cache_ttl_override" toml:"cache_ttl_override,omitempty"`
|
||||||
CacheServeStale bool `mapstructure:"cache_serve_stale" toml:"cache_serve_stale,omitempty"`
|
CacheServeStale bool `mapstructure:"cache_serve_stale" toml:"cache_serve_stale,omitempty"`
|
||||||
MaxConcurrentRequests *int `mapstructure:"max_concurrent_requests" toml:"max_concurrent_requests,omitempty" validate:"omitempty,gte=0"`
|
CacheFlushDomains []string `mapstructure:"cache_flush_domains" toml:"cache_flush_domains" validate:"max=256"`
|
||||||
DHCPLeaseFile string `mapstructure:"dhcp_lease_file_path" toml:"dhcp_lease_file_path" validate:"omitempty,file"`
|
MaxConcurrentRequests *int `mapstructure:"max_concurrent_requests" toml:"max_concurrent_requests,omitempty" validate:"omitempty,gte=0"`
|
||||||
DHCPLeaseFileFormat string `mapstructure:"dhcp_lease_file_format" toml:"dhcp_lease_file_format" validate:"required_unless=DHCPLeaseFile '',omitempty,oneof=dnsmasq isc-dhcp"`
|
DHCPLeaseFile string `mapstructure:"dhcp_lease_file_path" toml:"dhcp_lease_file_path" validate:"omitempty,file"`
|
||||||
DiscoverMDNS *bool `mapstructure:"discover_mdns" toml:"discover_mdns,omitempty"`
|
DHCPLeaseFileFormat string `mapstructure:"dhcp_lease_file_format" toml:"dhcp_lease_file_format" validate:"required_unless=DHCPLeaseFile '',omitempty,oneof=dnsmasq isc-dhcp"`
|
||||||
DiscoverARP *bool `mapstructure:"discover_arp" toml:"discover_arp,omitempty"`
|
DiscoverMDNS *bool `mapstructure:"discover_mdns" toml:"discover_mdns,omitempty"`
|
||||||
DiscoverDHCP *bool `mapstructure:"discover_dhcp" toml:"discover_dhcp,omitempty"`
|
DiscoverARP *bool `mapstructure:"discover_arp" toml:"discover_arp,omitempty"`
|
||||||
DiscoverPtr *bool `mapstructure:"discover_ptr" toml:"discover_ptr,omitempty"`
|
DiscoverDHCP *bool `mapstructure:"discover_dhcp" toml:"discover_dhcp,omitempty"`
|
||||||
DiscoverHosts *bool `mapstructure:"discover_hosts" toml:"discover_hosts,omitempty"`
|
DiscoverPtr *bool `mapstructure:"discover_ptr" toml:"discover_ptr,omitempty"`
|
||||||
DiscoverRefreshInterval int `mapstructure:"discover_refresh_interval" toml:"discover_refresh_interval,omitempty"`
|
DiscoverHosts *bool `mapstructure:"discover_hosts" toml:"discover_hosts,omitempty"`
|
||||||
ClientIDPref string `mapstructure:"client_id_preference" toml:"client_id_preference,omitempty" validate:"omitempty,oneof=host mac"`
|
DiscoverRefreshInterval int `mapstructure:"discover_refresh_interval" toml:"discover_refresh_interval,omitempty"`
|
||||||
MetricsQueryStats bool `mapstructure:"metrics_query_stats" toml:"metrics_query_stats,omitempty"`
|
ClientIDPref string `mapstructure:"client_id_preference" toml:"client_id_preference,omitempty" validate:"omitempty,oneof=host mac"`
|
||||||
MetricsListener string `mapstructure:"metrics_listener" toml:"metrics_listener,omitempty"`
|
MetricsQueryStats bool `mapstructure:"metrics_query_stats" toml:"metrics_query_stats,omitempty"`
|
||||||
Daemon bool `mapstructure:"-" toml:"-"`
|
MetricsListener string `mapstructure:"metrics_listener" toml:"metrics_listener,omitempty"`
|
||||||
AllocateIP bool `mapstructure:"-" toml:"-"`
|
Daemon bool `mapstructure:"-" toml:"-"`
|
||||||
|
AllocateIP bool `mapstructure:"-" toml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkConfig specifies configuration for networks where ctrld will handle requests.
|
// NetworkConfig specifies configuration for networks where ctrld will handle requests.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ctrld_test
|
package ctrld_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -103,6 +104,7 @@ func TestConfigValidation(t *testing.T) {
|
|||||||
{"invalid doh/doh3 endpoint", configWithInvalidDoHEndpoint(t), true},
|
{"invalid doh/doh3 endpoint", configWithInvalidDoHEndpoint(t), true},
|
||||||
{"invalid client id pref", configWithInvalidClientIDPref(t), true},
|
{"invalid client id pref", configWithInvalidClientIDPref(t), true},
|
||||||
{"doh endpoint without scheme", dohUpstreamEndpointWithoutScheme(t), false},
|
{"doh endpoint without scheme", dohUpstreamEndpointWithoutScheme(t), false},
|
||||||
|
{"maximum number of flush cache domains", configWithInvalidFlushCacheDomain(t), true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
@@ -275,3 +277,12 @@ func configWithInvalidClientIDPref(t *testing.T) *ctrld.Config {
|
|||||||
cfg.Service.ClientIDPref = "foo"
|
cfg.Service.ClientIDPref = "foo"
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func configWithInvalidFlushCacheDomain(t *testing.T) *ctrld.Config {
|
||||||
|
cfg := defaultConfig(t)
|
||||||
|
cfg.Service.CacheFlushDomains = make([]string, 257)
|
||||||
|
for i := range cfg.Service.CacheFlushDomains {
|
||||||
|
cfg.Service.CacheFlushDomains[i] = fmt.Sprintf("%d.com", i)
|
||||||
|
}
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|||||||
+8
-1
@@ -157,6 +157,13 @@ stale cached records (regardless of their TTLs) until upstream comes online.
|
|||||||
- Required: no
|
- Required: no
|
||||||
- Default: false
|
- Default: false
|
||||||
|
|
||||||
|
### cache_flush_domains
|
||||||
|
When `ctrld` receives query with domain name in `cache_flush_domains`, the local cache will be discarded
|
||||||
|
before serving the query.
|
||||||
|
|
||||||
|
- Type: array of strings
|
||||||
|
- Required: no
|
||||||
|
|
||||||
### max_concurrent_requests
|
### max_concurrent_requests
|
||||||
The number of concurrent requests that will be handled, must be a non-negative integer.
|
The number of concurrent requests that will be handled, must be a non-negative integer.
|
||||||
Tweaking this value depends on the capacity of your system.
|
Tweaking this value depends on the capacity of your system.
|
||||||
@@ -531,7 +538,7 @@ And within each policy, the rules are processed from top to bottom.
|
|||||||
### failover_rcodes
|
### failover_rcodes
|
||||||
For non success response, `failover_rcodes` allows the request to be forwarded to next upstream, if the response `RCODE` matches any value defined in `failover_rcodes`.
|
For non success response, `failover_rcodes` allows the request to be forwarded to next upstream, if the response `RCODE` matches any value defined in `failover_rcodes`.
|
||||||
|
|
||||||
- Type: array of string
|
- Type: array of strings
|
||||||
- Required: no
|
- Required: no
|
||||||
- Default: []
|
- Default: []
|
||||||
-
|
-
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
type Cacher interface {
|
type Cacher interface {
|
||||||
Get(Key) *Value
|
Get(Key) *Value
|
||||||
Add(Key, *Value)
|
Add(Key, *Value)
|
||||||
|
Purge()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key is the caching key for DNS message.
|
// Key is the caching key for DNS message.
|
||||||
@@ -34,15 +35,22 @@ type LRUCache struct {
|
|||||||
cacher *lru.ARCCache[Key, *Value]
|
cacher *lru.ARCCache[Key, *Value]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get looks up key's value from cache.
|
||||||
func (l *LRUCache) Get(key Key) *Value {
|
func (l *LRUCache) Get(key Key) *Value {
|
||||||
v, _ := l.cacher.Get(key)
|
v, _ := l.cacher.Get(key)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add adds a value to cache.
|
||||||
func (l *LRUCache) Add(key Key, value *Value) {
|
func (l *LRUCache) Add(key Key, value *Value) {
|
||||||
l.cacher.Add(key, value)
|
l.cacher.Add(key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Purge clears the cache.
|
||||||
|
func (l *LRUCache) Purge() {
|
||||||
|
l.cacher.Purge()
|
||||||
|
}
|
||||||
|
|
||||||
// NewLRUCache creates a new LRUCache instance with given size.
|
// NewLRUCache creates a new LRUCache instance with given size.
|
||||||
func NewLRUCache(size int) (*LRUCache, error) {
|
func NewLRUCache(size int) (*LRUCache, error) {
|
||||||
cacher, err := lru.NewARC[Key, *Value](size)
|
cacher, err := lru.NewARC[Key, *Value](size)
|
||||||
|
|||||||
Reference in New Issue
Block a user