Add dns.cache.optimizer as option to control the usage of expired/stale DNS queries while Pi-hole is looking for new ones. This option has always been available, we just make it more visible by assigning an individual config option for it.

Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
DL6ER 2023-02-11 10:12:12 +01:00
parent 37d9c15101
commit bcda8cc29a
No known key found for this signature in database
GPG Key ID: 00135ACBD90B28DD
10 changed files with 100 additions and 24 deletions

View File

@ -198,8 +198,6 @@ components:
type: string
listeningMode:
type: string
cacheSize:
type: integer
queryLogging:
type: boolean
cnameRecords:
@ -208,6 +206,13 @@ components:
type: string
port:
type: integer
cache:
type: object
properties:
size:
type: integer
optimizer:
type: integer
revServer:
type: object
properties:
@ -532,12 +537,14 @@ components:
interface: "eth0"
hostRecord: ""
listeningMode: "local"
cacheSize: 10000
queryLogging: true
cnameRecords:
- "*.example.com,default.example.com"
- "hourly.yetanother.com,yetanother.com,3600"
port: 53
cache:
size: 10000
optimizer: 3600
revServer:
active: false
cidr: "192.168.0.0/24"

View File

@ -902,6 +902,15 @@ components:
immortal:
type: integer
description: Number of immortal entries
optimized:
type: integer
description: Number of queries answered from stale cache entries
local:
type: integer
description: Number of queries answered locally
auth:
type: integer
description: Number of queries for authoritative zones
valid:
type: object
description: Number of valid entries
@ -927,6 +936,15 @@ components:
other:
type: integer
description: Number of valid other entries
extra:
type: object
properties:
forwarded:
type: integer
description: Number of forwarded queries
unanswered:
type: integer
description: Number of unanswered queries
examples:
errors:
messages:
@ -953,6 +971,9 @@ components:
evicted: 0
expired: 0
immortal: 0
optimized: 1
local: 84
auth: 0
valid:
a: 212
aaaa: 61
@ -961,6 +982,9 @@ components:
ds: 60
dnskey: 35
other: 14
extra:
forwarded: 46
unanswered: 0
parameters:
logs:

View File

@ -882,6 +882,9 @@ int api_info_cache(struct ftl_conn *api)
JSON_ADD_NUMBER_TO_OBJECT(cache, "size", ci.cache_size);
JSON_ADD_NUMBER_TO_OBJECT(cache, "inserted", ci.cache_inserted);
JSON_ADD_NUMBER_TO_OBJECT(cache, "evicted", ci.cache_live_freed);
JSON_ADD_NUMBER_TO_OBJECT(cache, "optimized", ci.stale_answered);
JSON_ADD_NUMBER_TO_OBJECT(cache, "local", ci.local_answered);
JSON_ADD_NUMBER_TO_OBJECT(cache, "auth", ci.auth_answered);
cJSON *valid = JSON_NEW_OBJECT();
JSON_ADD_NUMBER_TO_OBJECT(valid, "a", ci.valid.a);
JSON_ADD_NUMBER_TO_OBJECT(valid, "aaaa", ci.valid.aaaa);
@ -891,9 +894,15 @@ int api_info_cache(struct ftl_conn *api)
JSON_ADD_NUMBER_TO_OBJECT(valid, "dnskey", ci.valid.dnskey);
JSON_ADD_NUMBER_TO_OBJECT(valid, "other", ci.valid.other);
JSON_ADD_ITEM_TO_OBJECT(cache, "valid", valid);
JSON_ADD_NUMBER_TO_OBJECT(cache, "expired", ci.expired);
JSON_ADD_NUMBER_TO_OBJECT(cache, "immortal", ci.immortal);
cJSON *extra = JSON_NEW_OBJECT();
JSON_ADD_NUMBER_TO_OBJECT(extra, "forwarded", ci.forwarded_queries);
JSON_ADD_NUMBER_TO_OBJECT(extra, "unanswered", ci.unanswered_queries);
JSON_ADD_ITEM_TO_OBJECT(cache, "extra", extra);
cJSON *json = JSON_NEW_OBJECT();
JSON_ADD_ITEM_TO_OBJECT(json, "cache", cache);
JSON_SEND_OBJECT(json);

View File

@ -23,6 +23,9 @@ struct cache_info {
// looked up for the longest time is evicted.
int cache_live_freed;
int cache_inserted;
int local_answered;
int stale_answered;
int auth_answered;
// <valid> are cache entries with positive remaining TTL
struct valid {
int a;
@ -37,6 +40,9 @@ struct cache_info {
int expired;
// <immortal> cache records never expire (e.g. from /etc/hosts)
int immortal;
// extra properties of the cache
int unanswered_queries;
int forwarded_queries;
};
void get_dnsmasq_cache_info(struct cache_info *ci);

View File

@ -467,12 +467,6 @@ void initConfig(struct config *conf)
conf->dns.listeningMode.f = FLAG_RESTART_DNSMASQ | FLAG_ADVANCED_SETTING;
conf->dns.listeningMode.d.listeningMode = LISTEN_LOCAL;
conf->dns.cacheSize.k = "dns.cacheSize";
conf->dns.cacheSize.h = "Cache size of the DNS server. Note that expiring cache entries naturally make room for new insertions over time. Setting this number too high will have an adverse effect as not only more space is needed, but also lookup speed gets degraded in the 10,000+ range. dnsmasq may issue a warning when you go beyond 10,000+ cache entries.";
conf->dns.cacheSize.t = CONF_UINT;
conf->dns.cacheSize.f = FLAG_RESTART_DNSMASQ | FLAG_ADVANCED_SETTING;
conf->dns.cacheSize.d.ui = 2000u;
conf->dns.queryLogging.k = "dns.queryLogging";
conf->dns.queryLogging.h = "Log DNS queries and replies to pihole.log";
conf->dns.queryLogging.t = CONF_BOOL;
@ -492,6 +486,19 @@ void initConfig(struct config *conf)
conf->dns.port.f = FLAG_RESTART_DNSMASQ | FLAG_ADVANCED_SETTING;
conf->dns.port.d.ui = 53u;
// sub-struct dns.cache
conf->dns.cache.size.k = "dns.cache.size";
conf->dns.cache.size.h = "Cache size of the DNS server. Note that expiring cache entries naturally make room for new insertions over time. Setting this number too high will have an adverse effect as not only more space is needed, but also lookup speed gets degraded in the 10,000+ range. dnsmasq may issue a warning when you go beyond 10,000+ cache entries.";
conf->dns.cache.size.t = CONF_UINT;
conf->dns.cache.size.f = FLAG_RESTART_DNSMASQ | FLAG_ADVANCED_SETTING;
conf->dns.cache.size.d.ui = 10000u;
conf->dns.cache.optimizer.k = "dns.cache.optimizer";
conf->dns.cache.optimizer.h = "Query cache optimizer: If a DNS name exists in the cache, but its time-to-live has expired only recently, the data will be used anyway (a refreshing from upstream is triggered). This can improve DNS query delays especially over unreliable Internet connections. This feature comes at the expense of possibly sometimes returning out-of-date data and less efficient cache utilisation, since old data cannot be flushed when its TTL expires, so the cache becomes mostly least-recently-used. To mitigate issues caused by massively outdated DNS replies, the maximum overaging of cached records is limited. We strongly recommend staying below 86400 (1 day) with this option.";
conf->dns.cache.optimizer.t = CONF_UINT;
conf->dns.cache.optimizer.f = FLAG_RESTART_DNSMASQ | FLAG_ADVANCED_SETTING;
conf->dns.cache.optimizer.d.ui = 3600u;
// sub-struct dns.blocking
conf->dns.blocking.active.k = "dns.blocking.active";
conf->dns.blocking.active.h = "Should FTL block queries?";

View File

@ -102,7 +102,6 @@ struct enum_options {
// When new config items are added, the following places need to be updated:
// - src/config/config.c: New default item
// - src/dnsmasq_interface.c: sizeof(struct config) increases (see comment there)
// - test/pihole.toml: Add the new item to the test config file
struct config {
struct {
@ -125,10 +124,13 @@ struct config {
struct conf_item interface;
struct conf_item hostRecord;
struct conf_item listeningMode;
struct conf_item cacheSize;
struct conf_item queryLogging;
struct conf_item cnameRecords;
struct conf_item port;
struct {
struct conf_item size;
struct conf_item optimizer;
} cache;
struct {
struct conf_item active;
struct conf_item mode;

View File

@ -254,7 +254,7 @@ bool __attribute__((const)) write_dnsmasq_config(struct config *conf, bool test_
}
fputs("# Set the size of dnsmasq's cache. The default is 150 names. Setting the cache\n", pihole_conf);
fputs("# size to zero disables caching. Note: huge cache size impacts performance\n", pihole_conf);
fprintf(pihole_conf, "cache-size=%u\n", conf->dns.cacheSize.v.ui);
fprintf(pihole_conf, "cache-size=%u\n", conf->dns.cache.size.v.ui);
fputs("\n", pihole_conf);
fputs("# Return answers to DNS queries from /etc/hosts and interface-name and\n", pihole_conf);
@ -349,6 +349,12 @@ bool __attribute__((const)) write_dnsmasq_config(struct config *conf, bool test_
fprintf(pihole_conf, "host-record=%s\n", conf->dns.hostRecord.v.s);
}
if(conf->dns.cache.optimizer.v.ui > 0u)
{
fputs("# Use stale cache entries for a given number of seconds to optimize cache utilization\n", pihole_conf);
fprintf(pihole_conf, "use-stale-cache=%u\n", conf->dns.cache.optimizer.v.ui);
}
const char *interface = conf->dns.interface.v.s;
// Use eth0 as fallback interface if the interface is missing
if(strlen(interface) == 0)

View File

@ -1772,8 +1772,13 @@ void get_dnsmasq_cache_info(struct cache_info *ci)
{
memset(ci, 0, sizeof(struct cache_info));
ci->cache_size = daemon->cachesize;
ci->cache_live_freed = daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED];
ci->cache_inserted = daemon->metrics[METRIC_DNS_CACHE_INSERTED];
ci->cache_live_freed = daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED];
ci->local_answered = daemon->metrics[METRIC_DNS_LOCAL_ANSWERED];
ci->stale_answered = daemon->metrics[METRIC_DNS_STALE_ANSWERED];
ci->auth_answered = daemon->metrics[METRIC_DNS_AUTH_ANSWERED];
ci->unanswered_queries = daemon->metrics[METRIC_DNS_UNANSWERED_QUERY];
ci->forwarded_queries = daemon->metrics[METRIC_DNS_QUERIES_FORWARDED];
const time_t now = time(NULL);
for (int i=0; i < hash_size; i++)
for (struct crec *cache = hash_table[i]; cache; cache = cache->hash_next)

View File

@ -31,8 +31,6 @@
#include "files.h"
// add_to_fifo_buffer() u.a.
#include "log.h"
// Prototype of getCacheInformation()
#include "api/api.h"
// global variable daemonmode
#include "args.h"
// handle_realtime_signals()
@ -3307,10 +3305,10 @@ void FTL_dnsmasq_log(const char *payload, const int length)
int check_struct_sizes(void)
{
int result = 0;
// sizeof(struct conf_item) is 72 on x86_64 and 52 on x86_32
// number of config elements: CONFIG_ELEMENTS
result += check_one_struct("struct conf_item", sizeof(struct conf_item), 72, 52);
result += check_one_struct("struct config", sizeof(struct config), 8424, 6084);
result += check_one_struct("struct config", sizeof(struct config),
CONFIG_ELEMENTS*sizeof(struct conf_item),
CONFIG_ELEMENTS*sizeof(struct conf_item));
result += check_one_struct("queriesData", sizeof(queriesData), 72, 64);
result += check_one_struct("upstreamsData", sizeof(upstreamsData), 640, 628);
result += check_one_struct("clientsData", sizeof(clientsData), 672, 652);

View File

@ -167,12 +167,6 @@
# should always ask yourself if the first option doesn't work for you as well.
listeningMode = "LOCAL"
# Cache size of the DNS server. Note that expiring cache entries naturally make room
# for new insertions over time. Setting this number too high will have an adverse
# effect as not only more space is needed, but also lookup speed gets degraded in the
# 10,000+ range. dnsmasq may issue a warning when you go beyond 10,000+ cache entries.
cacheSize = 2000
# Log DNS queries and replies to pihole.log
queryLogging = true
@ -187,6 +181,24 @@
# Port used by the DNS server
port = 53
[dns.cache]
# Cache size of the DNS server. Note that expiring cache entries naturally make room
# for new insertions over time. Setting this number too high will have an adverse
# effect as not only more space is needed, but also lookup speed gets degraded in the
# 10,000+ range. dnsmasq may issue a warning when you go beyond 10,000+ cache entries.
size = 10000
# Query cache optimizer: If a DNS name exists in the cache, but its time-to-live has
# expired only recently, the data will be used anyway (a refreshing from upstream is
# triggered). This can improve DNS query delays especially over unreliable Internet
# connections. This feature comes at the expense of possibly sometimes returning
# out-of-date data and less efficient cache utilisation, since old data cannot be
# flushed when its TTL expires, so the cache becomes mostly least-recently-used. To
# mitigate issues caused by massively outdated DNS replies, the maximum overaging of
# cached records is limited. We strongly recommend staying below 86400 (1 day) with
# this option.
optimizer = 3600
[dns.blocking]
# Should FTL block queries?
active = true