]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
negative cache design.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 18 Aug 2008 15:00:17 +0000 (15:00 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Mon, 18 Aug 2008 15:00:17 +0000 (15:00 +0000)
git-svn-id: file:///svn/unbound/trunk@1197 be551aaa-1e26-0410-a405-d3ace91eadb9

util/fptr_wlist.c
validator/val_neg.c
validator/val_neg.h

index f8e60daff078ac0d02908363141fc5d00a80ce3b..412236a6e4159baeae030f52726b8081cf5dc324 100644 (file)
@@ -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;
 }
 
index 95ac25b702ae67a2f23832758d6fa5241e44f794..b7e263cad50ac01d7c7088d54490f47057e27be7 100644 (file)
  */
 #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,
index 5eb2753f84548febdc9c6a988a40f3b64209250a..857c6aff417e10d017b8d334ba9e99705688fb7f 100644 (file)
@@ -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.