mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-23 15:12:55 -05:00
negative cache design.
git-svn-id: file:///svn/unbound/trunk@1197 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
38396319c7
commit
bcec1a7593
3 changed files with 177 additions and 20 deletions
|
|
@ -166,7 +166,8 @@ fptr_whitelist_rbtree_cmp(int (*fptr) (const void *, const void *))
|
|||
else if(fptr == &anchor_cmp) return 1;
|
||||
else if(fptr == &canonical_tree_compare) return 1;
|
||||
else if(fptr == &context_query_cmp) return 1;
|
||||
else if(fptr == &val_neg_compare) return 1;
|
||||
else if(fptr == &val_neg_data_compare) return 1;
|
||||
else if(fptr == &val_neg_zone_compare) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,14 +43,23 @@
|
|||
*/
|
||||
#include "config.h"
|
||||
#include "validator/val_neg.h"
|
||||
#include "util/log.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
int val_neg_compare(const void* a, const void* b)
|
||||
int val_neg_data_compare(const void* a, const void* b)
|
||||
{
|
||||
struct val_neg_data* x = (struct val_neg_data*)a;
|
||||
struct val_neg_data* y = (struct val_neg_data*)b;
|
||||
int m;
|
||||
return dname_canon_lab_cmp(x->name, x->labs, y->name, y->labs, &m);
|
||||
}
|
||||
|
||||
int val_neg_zone_compare(const void* a, const void* b)
|
||||
{
|
||||
struct val_neg_zone* x = (struct val_neg_zone*)a;
|
||||
struct val_neg_zone* y = (struct val_neg_zone*)b;
|
||||
int m;
|
||||
if(x->dclass != y->dclass) {
|
||||
if(x->dclass < y->dclass)
|
||||
return -1;
|
||||
|
|
@ -67,8 +76,8 @@ struct val_neg_cache* val_neg_create()
|
|||
log_err("Could not create neg cache: out of memory");
|
||||
return NULL;
|
||||
}
|
||||
neg->max = 1024*1024; /* 1 M is about 5000(64bit)-10000(32) data */
|
||||
rbtree_init(&neg->tree, &val_neg_compare);
|
||||
neg->max = 1024*1024; /* 1 M is thousands of entries */
|
||||
rbtree_init(&neg->tree, &val_neg_zone_compare);
|
||||
lock_basic_init(&neg->lock);
|
||||
lock_protect(&neg->lock, neg, sizeof(*neg));
|
||||
return neg;
|
||||
|
|
@ -94,7 +103,7 @@ void neg_cache_delete(struct val_neg_cache* neg)
|
|||
struct val_neg_data* p, *np;
|
||||
if(!neg) return;
|
||||
lock_basic_destroy(&neg->lock);
|
||||
/* delete all the elements */
|
||||
/* delete all the zonedata elements */
|
||||
p = neg->first;
|
||||
while(p) {
|
||||
np = p->next;
|
||||
|
|
@ -102,17 +111,130 @@ void neg_cache_delete(struct val_neg_cache* neg)
|
|||
free(p);
|
||||
p = np;
|
||||
}
|
||||
/* delete all the zones in the tree */
|
||||
/* TODO */
|
||||
free(neg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create more space in negative cache
|
||||
* The oldest elements are deleted until enough space is present.
|
||||
* Empty zones are deleted.
|
||||
* @param neg: negative cache.
|
||||
* @param need: how many bytes are needed.
|
||||
*/
|
||||
static void neg_make_space(struct val_neg_cache* neg, size_t need)
|
||||
{
|
||||
/* delete elements until enough space or its empty */
|
||||
while(neg->last && (neg->max - neg->use) < need) {
|
||||
/* Delete data, zone */
|
||||
/* update parent ptrs of items beneath it */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the given zone, from the SOA owner name and class
|
||||
* @param neg: negative cache
|
||||
* @param soa: what to look for.
|
||||
* @return zone or NULL if not found.
|
||||
*/
|
||||
static struct val_neg_zone* neg_find_zone(struct val_neg_cache* neg,
|
||||
struct ub_packed_rrset_key* soa)
|
||||
{
|
||||
struct val_neg_zone lookfor;
|
||||
struct val_neg_zone* result;
|
||||
lookfor.node.key = &lookfor;
|
||||
lookfor.name = soa->rk.dname;
|
||||
lookfor.len = soa->rk.dname_len;
|
||||
lookfor.labs = dname_count_labels(lookfor.name);
|
||||
lookfor.dclass = ntohs(soa->rk.rrset_class);
|
||||
|
||||
result = (struct val_neg_zone*)
|
||||
rbtree_search(&neg->tree, lookfor.node.key);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new zone.
|
||||
* @param neg: negative cache
|
||||
* @param soa: what to look for.
|
||||
* @return zone or NULL if out of memory.
|
||||
* Other data may be deleted to make room for the new zone.
|
||||
*/
|
||||
static struct val_neg_zone* neg_create_zone(struct val_neg_cache* neg,
|
||||
struct ub_packed_rrset_key* soa)
|
||||
{
|
||||
struct val_neg_zone* zone;
|
||||
size_t need;
|
||||
|
||||
/* make space */
|
||||
need = sizeof(struct val_neg_zone) + soa->rk.dname_len;
|
||||
neg_make_space(neg, need);
|
||||
|
||||
/* create new item */
|
||||
zone = (struct val_neg_zone*)calloc(1, sizeof(*zone));
|
||||
if(!zone) {
|
||||
return NULL;
|
||||
}
|
||||
zone->node.key = zone;
|
||||
zone->name = memdup(soa->rk.dname, soa->rk.dname_len);
|
||||
if(!zone->name) {
|
||||
return NULL;
|
||||
}
|
||||
zone->len = soa->rk.dname_len;
|
||||
zone->labs = dname_count_labels(zone->name);
|
||||
zone->dclass = ntohs(soa->rk.rrset_class);
|
||||
|
||||
zone->soa_hash = soa->entry.hash;
|
||||
rbtree_init(&zone->tree, &val_neg_data_compare);
|
||||
|
||||
/* insert in tree */
|
||||
(void)rbtree_insert(&neg->tree, &zone->node);
|
||||
|
||||
/* find zone->parent */
|
||||
|
||||
|
||||
/* set this zone as parent for lower zones */
|
||||
}
|
||||
|
||||
/** find zone name of message, returns the SOA record */
|
||||
static struct ub_packed_rrset_key* reply_find_soa(struct reply_info* rep)
|
||||
{
|
||||
size_t i;
|
||||
for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){
|
||||
if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_SOA)
|
||||
return rep->rrsets[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep)
|
||||
{
|
||||
size_t i;
|
||||
struct ub_packed_rrset_key* soa;
|
||||
struct val_neg_zone* zone;
|
||||
/* find the zone name in message */
|
||||
soa = reply_find_soa(rep);
|
||||
if(!soa)
|
||||
return;
|
||||
|
||||
/* find or create the zone entry */
|
||||
lock_basic_lock(&neg->lock);
|
||||
zone = neg_find_zone(neg, soa);
|
||||
if(!zone) {
|
||||
if(!(zone = neg_create_zone(neg, soa))) {
|
||||
lock_basic_unlock(&neg->lock);
|
||||
log_err("out of memory adding negative zone");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert the NSECs */
|
||||
for(i=rep->an_numrrsets; i< rep->an_numrrsets+rep->ns_numrrsets; i++){
|
||||
if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC)
|
||||
continue;
|
||||
/* insert the NSEC */
|
||||
}
|
||||
lock_basic_unlock(&neg->lock);
|
||||
}
|
||||
|
||||
int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ struct val_neg_cache {
|
|||
* Because we use a rbtree for the data (quick lookup), we need
|
||||
* a big lock */
|
||||
lock_basic_t lock;
|
||||
/** The data rbtree for NSEC. contents of type val_neg_data */
|
||||
/** The zone rbtree. contents of type val_neg_zone */
|
||||
rbtree_t tree;
|
||||
/** the first and last in linked list of LRU of val_neg_data */
|
||||
struct val_neg_data* first;
|
||||
|
|
@ -74,6 +74,36 @@ struct val_neg_cache {
|
|||
size_t max;
|
||||
};
|
||||
|
||||
/**
|
||||
* Per Zone aggressive negative caching data.
|
||||
*/
|
||||
struct val_neg_zone {
|
||||
/** rbtree node element, key is this struct: the name */
|
||||
rbnode_t node;
|
||||
/** name; the key */
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
size_t len;
|
||||
/** labels in name */
|
||||
int labs;
|
||||
|
||||
/** pointer to parent zone in the negative cache */
|
||||
struct val_neg_zone* parent;
|
||||
|
||||
/** type of zone ; NSEC */
|
||||
|
||||
/** hash of zonename, SOA type, class, for lookup of SOA rrset */
|
||||
hashvalue_t soa_hash;
|
||||
|
||||
/** tree of NSEC data for this zone, sort by NSEC owner name */
|
||||
rbtree_t tree;
|
||||
/** the children that have NULL as a parent ptr */
|
||||
struct val_neg_data* child_first, *child_last;
|
||||
|
||||
/** class of node; host order */
|
||||
uint16_t dclass;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data element for aggressive negative caching.
|
||||
*/
|
||||
|
|
@ -89,23 +119,22 @@ struct val_neg_data {
|
|||
|
||||
/** pointer to parent node in the negative cache */
|
||||
struct val_neg_data* parent;
|
||||
/** linked list of items that have this one as parent, children */
|
||||
struct val_neg_data* child_first, *child_last;
|
||||
/** next and previous siblings in the list of childprent with the
|
||||
* same value for the parent pointer */
|
||||
struct val_neg_data* sibling_next, *sibling_prev;
|
||||
|
||||
/** the zone that this denial is part of */
|
||||
struct val_neg_zone* zone;
|
||||
|
||||
/** previous in LRU */
|
||||
struct val_neg_data* prev;
|
||||
/** next in LRU (next element was less recently used) */
|
||||
struct val_neg_data* next;
|
||||
|
||||
/** reference to NSEC rrset (parent side of a zone cut) */
|
||||
struct rrset_ref nsec_above;
|
||||
/** reference to SOA record for zone of nsec_above */
|
||||
struct rrset_ref soa_above;
|
||||
/** reference to NSEC rrset (child side of a zone cut - or elsewhere) */
|
||||
struct rrset_ref nsec_below;
|
||||
/** reference to SOA record for zone of nsec_below */
|
||||
struct rrset_ref soa_below;
|
||||
|
||||
/** class of node; host order */
|
||||
uint16_t dclass;
|
||||
/** hash of denial rrset: owner name, NSEC, class, for rrset lookup*/
|
||||
hashvalue_t nsec_hash;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -138,7 +167,12 @@ void neg_cache_delete(struct val_neg_cache* neg);
|
|||
/**
|
||||
* Comparison function for rbtree val neg data elements
|
||||
*/
|
||||
int val_neg_compare(const void* a, const void* b);
|
||||
int val_neg_data_compare(const void* a, const void* b);
|
||||
|
||||
/**
|
||||
* Comparison function for rbtree val neg zone elements
|
||||
*/
|
||||
int val_neg_zone_compare(const void* a, const void* b);
|
||||
|
||||
/**
|
||||
* Insert NSECs from this message into the negative cache for reference.
|
||||
|
|
|
|||
Loading…
Reference in a new issue