From 55f7bbc0514dc31b95f3050089582f65648334d0 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Fri, 15 Aug 2008 13:31:16 +0000 Subject: [PATCH] negative cache design. git-svn-id: file:///svn/unbound/trunk@1192 be551aaa-1e26-0410-a405-d3ace91eadb9 --- util/fptr_wlist.c | 2 + validator/val_neg.c | 128 +++++++++++++++++++++++++++++++++ validator/val_neg.h | 169 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 299 insertions(+) create mode 100644 validator/val_neg.c create mode 100644 validator/val_neg.h diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 956e2ae89..f8e60daff 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -61,6 +61,7 @@ #include "validator/val_nsec3.h" #include "validator/val_sigcrypt.h" #include "validator/val_kentry.h" +#include "validator/val_neg.h" #include "util/data/msgreply.h" #include "util/data/packed_rrset.h" #include "util/storage/slabhash.h" @@ -165,6 +166,7 @@ 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; return 0; } diff --git a/validator/val_neg.c b/validator/val_neg.c new file mode 100644 index 000000000..95ac25b70 --- /dev/null +++ b/validator/val_neg.c @@ -0,0 +1,128 @@ +/* + * validator/val_neg.c - validator aggressive negative caching functions. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with aggressive negative caching. + * This creates new denials of existance, and proofs for absence of types + * from cached NSEC records. + */ +#include "config.h" +#include "validator/val_neg.h" +#include "util/log.h" +#include "util/data/dname.h" + +int val_neg_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; + if(x->dclass != y->dclass) { + if(x->dclass < y->dclass) + return -1; + return 1; + } + return dname_canon_lab_cmp(x->name, x->labs, y->name, y->labs, &m); +} + +struct val_neg_cache* val_neg_create() +{ + struct val_neg_cache* neg = (struct val_neg_cache*)calloc(1, + sizeof(*neg)); + if(!neg) { + 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); + lock_basic_init(&neg->lock); + lock_protect(&neg->lock, neg, sizeof(*neg)); + return neg; +} + +int val_neg_apply_cfg(struct val_neg_cache* neg, struct config_file* cfg) +{ + /* TODO read max mem size from cfg */ + return 1; +} + +size_t val_neg_get_mem(struct val_neg_cache* neg) +{ + size_t result; + lock_basic_lock(&neg->lock); + result = sizeof(*neg) + neg->use; + lock_basic_unlock(&neg->lock); + return result; +} + +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 */ + p = neg->first; + while(p) { + np = p->next; + free(p->name); + free(p); + p = np; + } + free(neg); +} + +void val_neg_addreply(struct val_neg_cache* neg, 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_NSEC) + continue; + /* insert the NSEC */ + } +} + +int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len, + uint16_t qclass) +{ + /* lookup closest data record */ + + /* examine proof */ + + /* delete closest data record if expired */ + + /* if OK touch the LRU for it */ +} diff --git a/validator/val_neg.h b/validator/val_neg.h new file mode 100644 index 000000000..732e5dfd9 --- /dev/null +++ b/validator/val_neg.h @@ -0,0 +1,169 @@ +/* + * validator/val_neg.h - validator aggressive negative caching functions. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains helper functions for the validator module. + * The functions help with aggressive negative caching. + * This creates new denials of existance, and proofs for absence of types + * from cached NSEC records. + */ + +#ifndef VALIDATOR_VAL_NEG_H +#define VALIDATOR_VAL_NEG_H +#include "util/locks.h" +#include "util/rbtree.h" +#include "util/data/msgreply.h" +struct val_neg_data; +struct config_file; +struct reply_info; + +/** + * The negative cache. It is shared between the threads, so locked. + * Kept as validator-module-state. It refers back to the rrset cache for + * data elements. It can be out of date and contain conflicting data + * from zone content changes. + */ +struct val_neg_cache { + /** the big lock on the negative 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 */ + rbtree_t tree; + /** the first and last in linked list of LRU of val_neg_data */ + struct val_neg_data* first; + /** last in lru (least recently used element) */ + struct val_neg_data* last; + /** current memory in use (bytes) */ + size_t use; + /** max memory to use (bytes) */ + size_t max; +}; + +/** + * Data element for aggressive negative caching. + */ +struct val_neg_data { + /** 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 node in the negative cache */ + struct val_neg_data* parent; + + /** 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; +}; + +/** + * Create negative cache + * @return neg cache, empty or NULL on failure. + */ +struct val_neg_cache* val_neg_create(); + +/** + * Apply configuration settings to negative cache + * @param neg: negative cache. + * @param cfg: config options. + * @return false on error. + */ +int val_neg_apply_cfg(struct val_neg_cache* neg, struct config_file* cfg); + +/** + * see how much memory is in use by the negative cache. + * @param neg: negative cache + * @return number of bytes in use. + */ +size_t val_neg_get_mem(struct val_neg_cache* neg); + +/** + * Destroy negative cache. There must no longer be any other threads. + * @param neg: negative cache. + */ +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); + +/** + * Insert NSECs from this message into the negative cache for reference. + * @param neg: negative cache + * @param rep: reply with NSECs. + * Errors are ignored, means that storage is omitted. + */ +void val_neg_addreply(struct val_neg_cache* neg, struct reply_info* rep); + +/** + * Perform a DLV style lookup + * During the lookup, we could find out that data has expired. In that + * case the neg_cache entries are removed, and lookup fails. + * + * @param neg: negative cache. + * @param qname: name to look for + * @param len: length of qname. + * @param qclass: class to look in. + * @return + * 0 on error + * 0 if no proof of negative + * 1 if indeed negative was proven + * thus, qname DLV qclass does not exist. + */ +int val_neg_dlvlookup(struct val_neg_cache* neg, uint8_t* qname, size_t len, + uint16_t qclass); + +#endif /* VALIDATOR_VAL_NEG_H */