From d366a7a660c95d1a3b0a596d55c0e39bc1a60fed Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Wed, 4 Apr 2007 13:02:13 +0000 Subject: [PATCH] Memory layout rrsets. git-svn-id: file:///svn/unbound/trunk@230 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 1 + util/data/msgreply.h | 67 +++++++++++++++++++ util/data/packed_rrset.c | 46 +++++++++++++ util/data/packed_rrset.h | 137 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 util/data/packed_rrset.c create mode 100644 util/data/packed_rrset.h diff --git a/doc/Changelog b/doc/Changelog index 5bd862272..05a166cf5 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,7 @@ 4 April 2007: Wouter - moved to version 0.3. - added util/data/dname.c + - layout of memory for rrsets. 3 April 2007: Wouter - detect sign of msghdr.msg_iovlen so that the cast to that type diff --git a/util/data/msgreply.h b/util/data/msgreply.h index 5d7dafb93..7c70cc0dc 100644 --- a/util/data/msgreply.h +++ b/util/data/msgreply.h @@ -42,7 +42,9 @@ #ifndef UTIL_DATA_MSGREPLY_H #define UTIL_DATA_MSGREPLY_H #include "util/storage/lruhash.h" +#include "util/data/packed_rrset.h" struct comm_reply; +struct alloc_cache; /** * Structure to store query information that makes answers to queries @@ -61,10 +63,25 @@ struct query_info { int has_cd; }; +/** + * Information to reference an rrset + */ +struct rrset_ref { + /** the key with lock, and ptr to packed data. */ + struct packed_rrset_key* key; + /** id needed */ + rrset_id_t id; +}; + /** * Structure to store DNS query and the reply packet. * To use it, copy over the flags from reply and modify using flags from * the query (RD,CD if not AA). prepend ID. + * + * Memory layout is: + * o struct + * o rrset_ref array + * o packed_rrset_key* array. */ struct reply_info { /** the reply packet, skips ID and flags, @@ -74,6 +91,34 @@ struct reply_info { size_t replysize; /** the flags for the answer, host order. */ uint16_t flags; + + /** + * network order counts: qdcount ancount nscount arcount. + * so this is wireformat for the counts as they appear in the message. + * If qdcount is not 0, then it is 1, and the data that appears + * in the reply is the same as the query_info. + */ + uint16_t counts[4]; + + /** Total number of rrsets in reply: ancount+nscount+arcount. */ + size_t num_rrsets; + + /** + * List of pointers (only) to the rrsets in the order in which + * They appear in the reply message. + * number of elements is ancount+nscount+arcount. + * this is a pointer to that array. + */ + struct packed_rrset_key** rrsets; + + /** + * Packed array of ids (see counts) and pointers to packed_rrset_key. + * The number equals ancount+nscount+arcount. + * These are sorted in ascending pointer, the locking order. So + * this list can be locked (and id, ttl checked), to see if + * all the data is available and recent enough. + */ + struct rrset_ref ref[1]; }; /** @@ -98,6 +143,28 @@ struct msgreply_entry { */ int query_info_parse(struct query_info* m, ldns_buffer* query); +/** + * Parse query reply. + * Fills in preallocated query_info structure (with ptr into buffer). + * Allocates reply_info and packed_rrsets. These are not yet added to any + * caches or anything, this is only parsing. Returns formerror on qdcount > 1. + * @param pkt: the packet buffer. Must be positioned after the query section. + * @param alloc: creates packed rrset key structures. + * @param rep: allocated reply_info is returned (only on no error). + * @param qinf: query_info is returned (only on no error). + * @return: zero is OK, or error code in case of error. + */ +int reply_info_parse(ldns_buffer* pkt, struct alloc_cache* alloc, + struct query_info* qinf, struct reply_info* rep); + +/** + * Delete reply_info and packed_rrsets (while they are not yet added to the + * hashtables.). Returns rrsets to the alloc cache. + * @param rep: reply_info to delete. + * @param alloc: where to return rrset structures to. + */ +void reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc); + /** * Allocate and copy the qname (obtained from query_info_parse()). * @param m: the queryinfo structure. diff --git a/util/data/packed_rrset.c b/util/data/packed_rrset.c new file mode 100644 index 000000000..5053a75ad --- /dev/null +++ b/util/data/packed_rrset.c @@ -0,0 +1,46 @@ +/* + * util/data/packed_rrset.c - data storage for a set of resource records. + * + * 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 the data storage for RRsets. + */ + +#include "config.h" +#include "util/data/packed_rrset.h" +#include "util/log.h" + + diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h new file mode 100644 index 000000000..8592a6933 --- /dev/null +++ b/util/data/packed_rrset.h @@ -0,0 +1,137 @@ +/* + * util/data/packed_rrset.h - data storage for a set of resource records. + * + * 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 the data storage for RRsets. + */ + +#ifndef UTIL_DATA_PACKED_RRSET_H +#define UTIL_DATA_PACKED_RRSET_H +#include "util/storage/lruhash.h" + +/** type used to uniquely identify rrsets. Cannot be reused without + * clearing the cache. */ +typedef uint64_t rrset_id_t; + +/** + * This structure contains an RRset. A set of resource records that + * share the same domain name, type and class. + * + * Due to memory management and threading, the key structure cannot be + * deleted, although the data can be. The id can be set to 0 to store and the + * structure can be recycled with a new id. + */ +struct packed_rrset_key { + /** + * entry into hashtable. Note the lock is never destroyed, + * even when this key is retired to the cache. + * the data pointer (if not null) points to a struct packed_rrset. + */ + struct lruhash_entry entry; + /** + * the ID of this rrset. unique, based on threadid + sequenceno. + * ids are not reused, except after flushing the cache. + * zero is an unused entry, and never a valid id. + * Check this value after getting entry.lock. + * The other values in this struct may only be altered after changing + * the id (which needs a writelock on entry.lock). + */ + rrset_id_t id; + + /** + * The domain name. If not null (for id=0) it is allocated, and + * contains the wireformat domain name. + * This dname is canonicalized. + * After the dname uint16_t type and uint16_t class is stored + * in wireformat. + */ + uint8_t* dname; + /** + * Length of the domain name, including last 0 root octet. + * The value+sizeof(uint16_t)*2 is actually allocated. + */ + size_t dname_len; +}; + +/** + * RRset data. + * + * The data is packed, stored contiguously in memory. + * memory layout: + * o base struct + * o rr_data uint8_t* array + * o rr_len size_t array + * o rr_ttl uint32_t array + * o rr_data rdata wireformats + * o rrsig_data rdata wireformat + * + * Rdata is stored in wireformat. The dname is stored in wireformat. + * TTLs are stored as absolute values (and could be expired). + * + * You need the packed_rrset_key to know dname, type, class of the + * resource records in this RRset. (if signed the rrsig gives the type too). + * + * On the wire an RR is: + * name, type, class, ttl, rdlength, rdata. + * So we need to send the following per RR: + * key.dname, ttl, rr_data[i]. + * since key.dname ends with type and class. + * and rr_data starts with the rdlength. + * the ttl value to send changes due to time. + */ +struct packed_rrset { + /** TTL (in seconds like time()) of the rrset */ + uint32_t ttl; + /** number of rrs. */ + size_t num; + /** + * Array of pointers to every rr's rdata. + * The rr_data[i] rdata is stored in uncompressed wireformat. + * The first uint16_t of rr_data[i] is network format rdlength. + */ + uint8_t** rr_data; + /** length of every rr's rdata, rr_len[i] is size of rr_data[i]. */ + size_t* rr_len; + /** TTL of every rr (equal or bigger than the rrset ttl). */ + uint32_t* rr_ttl; + /** if this rrset is signed with an RRSIG, it is stored here. */ + uint8_t* rrsig_data; + /** length of rrsig rdata (only examine if rrsig_data is not null) */ + size_t rrsig_len; +}; + +#endif /* UTIL_DATA_PACKED_RRSET_H */ -- 2.47.2