Reimplement DNS cache metrics in the light of arbitrary RRTYPE caching
Signed-off-by: DL6ER <dl6er@dl6er.de>
This commit is contained in:
parent
a1332582ff
commit
c05502f24a
|
@ -914,27 +914,20 @@ components:
|
|||
type: integer
|
||||
description: Number of immortal entries
|
||||
content:
|
||||
type: object
|
||||
description: Number of valid DNS cache entries
|
||||
properties:
|
||||
a:
|
||||
type: integer
|
||||
description: Number of valid A (IPv4) entries
|
||||
aaaa:
|
||||
type: integer
|
||||
description: Number of valid AAAA (IPv6) entries
|
||||
cname:
|
||||
type: integer
|
||||
description: Number of valid CNAME entries
|
||||
ds:
|
||||
type: integer
|
||||
description: Number of valid DS entries
|
||||
dnskey:
|
||||
type: integer
|
||||
description: Number of valid DNSKEY entries
|
||||
other:
|
||||
type: integer
|
||||
description: Number of valid other entries
|
||||
type: array
|
||||
description: Array of valid DNS cache entries
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: integer
|
||||
description: RR type of cache entry
|
||||
name:
|
||||
type: string
|
||||
description: RR name of cache entry
|
||||
count:
|
||||
type: string
|
||||
description: Number of cache entries for this RR type
|
||||
replies:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1038,12 +1031,24 @@ components:
|
|||
expired: 0
|
||||
immortal: 0
|
||||
content:
|
||||
a: 212
|
||||
aaaa: 61
|
||||
cname: 14
|
||||
ds: 60
|
||||
dnskey: 35
|
||||
other: 14
|
||||
- type: 0
|
||||
name: "OTHER"
|
||||
count: 0
|
||||
- type: 1
|
||||
name: "A"
|
||||
count: 17
|
||||
- type: 28
|
||||
name: "AAAA"
|
||||
count: 5
|
||||
- type: 5
|
||||
name: "CNAME"
|
||||
count: 2
|
||||
- type: 43
|
||||
name: "DS"
|
||||
count: 15
|
||||
- type: 48
|
||||
name: "DNSKEY"
|
||||
count: 16
|
||||
replies:
|
||||
optimized: 1
|
||||
local: 84
|
||||
|
|
|
@ -920,13 +920,20 @@ int api_info_metrics(struct ftl_conn *api)
|
|||
JSON_ADD_NUMBER_TO_OBJECT(cache, "expired", metrics.dns.cache.expired);
|
||||
JSON_ADD_NUMBER_TO_OBJECT(cache, "immortal", metrics.dns.cache.immortal);
|
||||
|
||||
cJSON *content = JSON_NEW_OBJECT();
|
||||
JSON_ADD_NUMBER_TO_OBJECT(content, "a", metrics.dns.cache.content.a);
|
||||
JSON_ADD_NUMBER_TO_OBJECT(content, "aaaa", metrics.dns.cache.content.aaaa);
|
||||
JSON_ADD_NUMBER_TO_OBJECT(content, "cname", metrics.dns.cache.content.cname);
|
||||
JSON_ADD_NUMBER_TO_OBJECT(content, "ds", metrics.dns.cache.content.ds);
|
||||
JSON_ADD_NUMBER_TO_OBJECT(content, "dnskey", metrics.dns.cache.content.dnskey);
|
||||
JSON_ADD_NUMBER_TO_OBJECT(content, "other", metrics.dns.cache.content.other);
|
||||
cJSON *content = JSON_NEW_ARRAY();
|
||||
for(unsigned int i = 0; i < RRTYPES; i++)
|
||||
{
|
||||
// Skip empty entries
|
||||
if(metrics.dns.cache.content[i].count == 0)
|
||||
continue;
|
||||
|
||||
// Add this entry to the array
|
||||
cJSON *obj = JSON_NEW_OBJECT();
|
||||
JSON_ADD_NUMBER_TO_OBJECT(obj, "type", metrics.dns.cache.content[i].type);
|
||||
JSON_REF_STR_IN_OBJECT(obj, "name", rrtype_name(metrics.dns.cache.content[i].type));
|
||||
JSON_ADD_NUMBER_TO_OBJECT(obj, "count", metrics.dns.cache.content[i].count);
|
||||
JSON_ADD_ITEM_TO_ARRAY(content, obj);
|
||||
}
|
||||
JSON_ADD_ITEM_TO_OBJECT(cache, "content", content);
|
||||
|
||||
cJSON *replies = JSON_NEW_OBJECT();
|
||||
|
|
|
@ -146,6 +146,21 @@ unsigned short rrtype(char *in)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Pi-hole function: return name of RR type */
|
||||
const char *rrtype_name(unsigned short type)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if(type == 0)
|
||||
return "OTHER";
|
||||
|
||||
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
||||
if (typestr[i].type == type)
|
||||
return typestr[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void next_uid(struct crec *crecp)
|
||||
{
|
||||
static unsigned int uid = 0;
|
||||
|
@ -1865,7 +1880,16 @@ static void dump_cache_entry(struct crec *cache, time_t now)
|
|||
/***************** Pi-hole modification *****************/
|
||||
void get_dnsmasq_metrics(struct metrics *ci)
|
||||
{
|
||||
// Prepare the metrics struct
|
||||
memset(ci, 0, sizeof(struct metrics));
|
||||
ci->dns.cache.content[RRTYPE_OTHER].type = 0;
|
||||
ci->dns.cache.content[RRTYPE_A].type = T_A; // A
|
||||
ci->dns.cache.content[RRTYPE_AAAA].type = T_AAAA; // AAAA
|
||||
ci->dns.cache.content[RRTYPE_CNAME].type = T_CNAME; // CNAME
|
||||
ci->dns.cache.content[RRTYPE_DS].type = T_DS; // DNSKEY
|
||||
ci->dns.cache.content[RRTYPE_DNSKEY].type = T_DNSKEY; // DNSKEY
|
||||
|
||||
// General DNS cache metrics
|
||||
ci->dns.cache.size = daemon->cachesize;
|
||||
ci->dns.cache.inserted = daemon->metrics[METRIC_DNS_CACHE_INSERTED];
|
||||
ci->dns.cache.live_freed = daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED];
|
||||
|
@ -1874,30 +1898,44 @@ void get_dnsmasq_metrics(struct metrics *ci)
|
|||
ci->dns.auth_answered = daemon->metrics[METRIC_DNS_AUTH_ANSWERED];
|
||||
ci->dns.unanswered_queries = daemon->metrics[METRIC_DNS_UNANSWERED_QUERY];
|
||||
ci->dns.forwarded_queries = daemon->metrics[METRIC_DNS_QUERIES_FORWARDED];
|
||||
|
||||
// DNS cache content metrics
|
||||
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)
|
||||
if(cache->ttd >= now || cache->flags & F_IMMORTAL)
|
||||
{
|
||||
if (cache->flags & F_IPV4)
|
||||
ci->dns.cache.content.a++;
|
||||
ci->dns.cache.content[RRTYPE_A].count++;
|
||||
else if (cache->flags & F_IPV6)
|
||||
ci->dns.cache.content.aaaa++;
|
||||
ci->dns.cache.content[RRTYPE_AAAA].count++;
|
||||
else if (cache->flags & F_CNAME)
|
||||
ci->dns.cache.content.cname++;
|
||||
ci->dns.cache.content[RRTYPE_CNAME].count++;
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if (cache->flags & F_DS)
|
||||
ci->dns.cache.content.ds++;
|
||||
ci->dns.cache.content[RRTYPE_DS].count++;
|
||||
else if (cache->flags & F_DNSKEY)
|
||||
ci->dns.cache.content.dnskey++;
|
||||
ci->dns.cache.content[RRTYPE_DNSKEY].count++;
|
||||
#endif
|
||||
else if(cache->flags & F_RR)
|
||||
{
|
||||
// Find the first empty slot or the slot with the same type
|
||||
for(unsigned int i = RRTYPE_MAX; i < RRTYPES; i++)
|
||||
{
|
||||
if(ci->dns.cache.content[i].type == cache->addr.rr.rrtype || ci->dns.cache.content[i].type == 0)
|
||||
{
|
||||
ci->dns.cache.content[i].type = cache->addr.rr.rrtype;
|
||||
ci->dns.cache.content[i].count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ci->dns.cache.content.other++;
|
||||
// cache->flags & F_RR --> cache->addr.rr.rrtype
|
||||
// Needs (USHRT_MAX*sizeof(int)) bytes of memory
|
||||
ci->dns.cache.content[RRTYPE_OTHER].count++;
|
||||
|
||||
if(cache->flags & F_IMMORTAL)
|
||||
ci->dns.cache.immortal++;
|
||||
|
||||
}
|
||||
else
|
||||
ci->dns.cache.expired++;
|
||||
|
|
|
@ -10,6 +10,20 @@
|
|||
#ifndef METRICS_H
|
||||
#define METRICS_H
|
||||
|
||||
// defined in src/dnsmasq/cache.c
|
||||
const char *rrtype_name(unsigned short type);
|
||||
|
||||
enum rrtype_array {
|
||||
RRTYPE_OTHER = 0,
|
||||
RRTYPE_A,
|
||||
RRTYPE_AAAA,
|
||||
RRTYPE_CNAME,
|
||||
RRTYPE_DS,
|
||||
RRTYPE_DNSKEY,
|
||||
RRTYPE_MAX
|
||||
};
|
||||
|
||||
#define RRTYPES RRTYPE_MAX+10
|
||||
struct metrics
|
||||
{
|
||||
struct dns
|
||||
|
@ -33,15 +47,10 @@ struct metrics
|
|||
// <immortal> cache records never expire (e.g. from /etc/hosts)
|
||||
int immortal;
|
||||
// <content> are cache entries with positive remaining TTL
|
||||
struct content
|
||||
{
|
||||
int a;
|
||||
int aaaa;
|
||||
int cname;
|
||||
int ds;
|
||||
int dnskey;
|
||||
int other;
|
||||
} content;
|
||||
struct content {
|
||||
uint16_t type;
|
||||
int count;
|
||||
} content[RRTYPES];
|
||||
} cache;
|
||||
int local_answered;
|
||||
int forwarded_queries;
|
||||
|
|
Loading…
Reference in New Issue