# more slabs reduce lock contention, but fragment memory usage.
# rrset-cache-slabs: 4
+ # the time to live (TTL) value for cached roundtrip times and
+ # EDNS version information for hosts. In seconds.
+ # infra-host-ttl: 900
+
+ # the time to live (TTL) value for cached lame delegations. In sec.
+ # infra-lame-ttl: 900
+
+ # the number of slabs to use for the Infrastructure cache.
+ # the number of slabs must be a power of 2.
+ # more slabs reduce lock contention, but fragment memory usage.
+ # infra-cache-slabs: 4
+
+ # the maximum number of hosts that are cached (roundtrip times, EDNS).
+ # infra-cache-numhosts: 1000
+
+ # the maximum number of lame zones per host that are cached.
+ # infra-cache-numlame: 1000
+
# Enable IPv4, "yes" or "no".
# do-ip4: yes
.It \fBrrset-cache-slabs:\fR <number>
Number of slabs in the RRset cache. Slabs reduce lock contention by threads.
Must be set to a power of 2.
+.It \fBinfra-host-ttl:\fR <seconds>
+Time to live for entries in the host cache. The host cache contains
+roundtrip timing and EDNS support information. Default is 900.
+.It \fBinfra-lame-ttl:\fR <seconds>
+The time to live when a delegation is discovered to be lame. Default is 900.
+.It \fBinfra-cache-slabs:\fR <number>
+Number of slabs in the infrastructure cache. Slabs reduce lock contention
+by threads. Must be set to a power of 2.
+.It \fBinfra-cache-numhosts:\fR <number>
+Number of hosts for which information is cached. Default is 1000.
+.It \fBinfra-cache-numlame:\fR <number>
+Number of zones per host for which lameness is cached. Default is 1000.
.It \fBdo-ip4:\fR <yes or no>
Enable or disable whether ip4 queries are answered. Default is yes.
.It \fBdo-ip6:\fR <yes or no>
#include "util/storage/lookup3.h"
#include "util/log.h"
#include "util/net_help.h"
+#include "util/config_file.h"
/** calculate size for the hashtable, does not count size of lameness,
* so the hashtable is a fixed number of items */
free(data);
}
-struct slabhash*
+struct infra_cache*
infra_create(struct config_file* cfg)
{
+ struct infra_cache* infra = (struct infra_cache*)calloc(1,
+ sizeof(struct infra_cache));
/* TODO: use config settings */
/* the size of the lameness tables are not counted */
- size_t maxmem = HOST_DEFAULT_SIZE * (sizeof(struct infra_host_key) +
- sizeof(struct infra_host_data));
- struct slabhash* infra = slabhash_create(HASH_DEFAULT_SLABS,
+ size_t maxmem = cfg->infra_cache_numhosts *
+ (sizeof(struct infra_host_key)+sizeof(struct infra_host_data));
+ infra->hosts = slabhash_create(cfg->infra_cache_slabs,
INFRA_HOST_STARTSIZE, maxmem, &infra_host_sizefunc,
&infra_host_compfunc, &infra_host_delkeyfunc,
&infra_host_deldatafunc, NULL);
+ if(!infra->hosts) {
+ free(infra);
+ return NULL;
+ }
+ infra->host_ttl = cfg->host_ttl;
+ infra->lame_ttl = cfg->lame_ttl;
+ infra->max_lame = cfg->infra_cache_numlame;
return infra;
}
void
-infra_delete(struct slabhash* infra)
+infra_delete(struct infra_cache* infra)
{
if(!infra)
return;
- slabhash_delete(infra);
+ slabhash_delete(infra->hosts);
+ free(infra);
}
/** calculate the hash value for a host key */
/** lookup version that does not check host ttl (you check it) */
static struct lruhash_entry*
-infra_lookup_host_nottl(struct slabhash* infra,
+infra_lookup_host_nottl(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr)
{
struct infra_host_key k;
k.entry.hash = hash_addr(addr, addrlen);
k.entry.key = (void*)&k;
k.entry.data = NULL;
- return slabhash_lookup(infra, k.entry.hash, &k, wr);
+ return slabhash_lookup(infra->hosts, k.entry.hash, &k, wr);
}
struct infra_host_data*
-infra_lookup_host(struct slabhash* infra,
+infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
time_t timenow, struct infra_host_key** key)
{
* @return: the new entry or NULL on malloc failure.
*/
static struct lruhash_entry*
-new_host_entry(struct sockaddr_storage* addr, socklen_t addrlen, time_t tm)
+new_host_entry(struct infra_cache* infra, struct sockaddr_storage* addr,
+ socklen_t addrlen, time_t tm)
{
struct infra_host_data* data;
struct infra_host_key* key = (struct infra_host_key*)malloc(
key->entry.data = (void*)data;
key->addrlen = addrlen;
memcpy(&key->addr, addr, addrlen);
- data->ttl = tm + HOST_TTL;
+ data->ttl = tm + infra->host_ttl;
data->lameness = NULL;
data->edns_version = 0;
rtt_init(&data->rtt);
}
int
-infra_host(struct slabhash* infra, struct sockaddr_storage* addr,
+infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, time_t timenow, int* edns_vs, int* to)
{
struct lruhash_entry* e = infra_lookup_host_nottl(infra, addr,
/* if its still there we have a writelock, init */
/* re-initialise */
data = (struct infra_host_data*)e->data;
- data->ttl = timenow + HOST_TTL;
+ data->ttl = timenow + infra->host_ttl;
rtt_init(&data->rtt);
/* do not touch lameness, it may be valid still */
data->edns_version = 0;
}
if(!e) {
/* insert new entry */
- if(!(e = new_host_entry(addr, addrlen, timenow)))
+ if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
return 0;
data = (struct infra_host_data*)e->data;
*to = rtt_timeout(&data->rtt);
*edns_vs = data->edns_version;
- slabhash_insert(infra, e->hash, e, data, NULL);
+ slabhash_insert(infra->hosts, e->hash, e, data, NULL);
return 1;
}
/* use existing entry */
}
int
-infra_set_lame(struct slabhash* infra,
+infra_set_lame(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, time_t timenow)
{
k->entry.hash = hash_lameness(name, namelen);
k->entry.key = (void*)k;
k->entry.data = (void*)d;
- d->ttl = timenow + HOST_LAME_TTL;
+ d->ttl = timenow + infra->lame_ttl;
k->namelen = namelen;
e = infra_lookup_host_nottl(infra, addr, addrlen, 1);
if(!e) {
/* insert it */
- if(!(e = new_host_entry(addr, addrlen, timenow))) {
+ if(!(e = new_host_entry(infra, addr, addrlen, timenow))) {
free(k->zonename);
free(k);
free(d);
if(!data->lameness) {
/* create hash table if not there already */
data->lameness = lruhash_create(INFRA_LAME_STARTSIZE,
- INFRA_LAME_MAXMEM*(sizeof(struct infra_lame_key)+
+ infra->max_lame*(sizeof(struct infra_lame_key)+
sizeof(struct infra_lame_data)), infra_lame_sizefunc,
infra_lame_compfunc, infra_lame_delkeyfunc,
infra_lame_deldatafunc, NULL);
if(!data->lameness) {
log_err("set_lame: malloc failure");
- if(needtoinsert) slabhash_insert(infra, e->hash, e,
- e->data, NULL);
+ if(needtoinsert) slabhash_insert(infra->hosts,
+ e->hash, e, e->data, NULL);
else lock_rw_unlock(&e->lock);
free(k->zonename);
free(k);
lruhash_insert(data->lameness, k->entry.hash, &k->entry, d, NULL);
if(needtoinsert)
- slabhash_insert(infra, e->hash, e, e->data, NULL);
+ slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else lock_rw_unlock(&e->lock);
return 1;
}
int
-infra_rtt_update(struct slabhash* infra,
+infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int roundtrip, time_t timenow)
{
struct infra_host_data* data;
int needtoinsert = 0;
if(!e) {
- if(!(e = new_host_entry(addr, addrlen, timenow)))
+ if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
return 0;
needtoinsert = 1;
}
/* have an entry, update the rtt, and the ttl */
data = (struct infra_host_data*)e->data;
- data->ttl = timenow + HOST_TTL;
+ data->ttl = timenow + infra->host_ttl;
if(roundtrip == -1)
rtt_lost(&data->rtt);
else rtt_update(&data->rtt, roundtrip);
if(needtoinsert)
- slabhash_insert(infra, e->hash, e, e->data, NULL);
+ slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else lock_rw_unlock(&e->lock);
return 1;
}
int
-infra_edns_update(struct slabhash* infra,
+infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int edns_version, time_t timenow)
{
struct infra_host_data* data;
int needtoinsert = 0;
if(!e) {
- if(!(e = new_host_entry(addr, addrlen, timenow)))
+ if(!(e = new_host_entry(infra, addr, addrlen, timenow)))
return 0;
needtoinsert = 1;
}
/* have an entry, update the rtt, and the ttl */
data = (struct infra_host_data*)e->data;
- data->ttl = timenow + HOST_TTL;
+ data->ttl = timenow + infra->host_ttl;
data->edns_version = edns_version;
if(needtoinsert)
- slabhash_insert(infra, e->hash, e, e->data, NULL);
+ slabhash_insert(infra->hosts, e->hash, e, e->data, NULL);
else lock_rw_unlock(&e->lock);
return 1;
}
time_t ttl;
};
-/** default TTL value for host information, in seconds */
-#define HOST_TTL 900
-/** default TTL for Lameness information, in seconds */
-#define HOST_LAME_TTL 900
-/** default size of the host cache, number of entries */
-#define HOST_DEFAULT_SIZE 1000
+/**
+ * Infra cache
+ */
+struct infra_cache {
+ /** The hash table with hosts */
+ struct slabhash* hosts;
+ /** TTL value for host information, in seconds */
+ int host_ttl;
+ /** TTL for Lameness information, in seconds */
+ int lame_ttl;
+ /** infra lame cache max memory per host, for this many entries */
+ size_t max_lame;
+};
+
/** infra host cache default hash lookup size */
#define INFRA_HOST_STARTSIZE 32
/** infra lame cache default hash lookup size */
#define INFRA_LAME_STARTSIZE 2
-/** infra lame cache max memory per host, for this many entries */
-#define INFRA_LAME_MAXMEM 1000
/**
* Create infra cache.
* @param cfg: config parameters.
* @return: new infra cache, or NULL.
*/
-struct slabhash* infra_create(struct config_file* cfg);
+struct infra_cache* infra_create(struct config_file* cfg);
/**
* Delete infra cache.
* @param infra: infrastructure cache to delete.
*/
-void infra_delete(struct slabhash* infra);
+void infra_delete(struct infra_cache* infra);
/**
* Lookup host data
* @param key: the key for the host, returned so caller can unlock when done.
* @return: host data or NULL if not found or expired.
*/
-struct infra_host_data* infra_lookup_host(struct slabhash* infra,
+struct infra_host_data* infra_lookup_host(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, int wr,
time_t timenow, struct infra_host_key** key);
* @param to: timeout to use, is returned.
* @return: 0 on error.
*/
-int infra_host(struct slabhash* infra, struct sockaddr_storage* addr,
+int infra_host(struct infra_cache* infra, struct sockaddr_storage* addr,
socklen_t addrlen, time_t timenow, int* edns_vs, int* to);
/**
* @param timenow: what time it is now.
* @return: 0 on error.
*/
-int infra_set_lame(struct slabhash* infra,
+int infra_set_lame(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
uint8_t* name, size_t namelen, time_t timenow);
* @param timenow: what time it is now.
* @return: 0 on error.
*/
-int infra_rtt_update(struct slabhash* infra,
+int infra_rtt_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int roundtrip, time_t timenow);
* @param timenow: what time it is now.
* @return: 0 on error.
*/
-int infra_edns_update(struct slabhash* infra,
+int infra_edns_update(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen,
int edns_version, time_t timenow);
int one = 1;
uint8_t* zone = (uint8_t*)"\007example\003com\000";
size_t zonelen = 13;
- struct slabhash* slab;
+ struct infra_cache* slab;
struct config_file* cfg = config_create();
time_t now = 0;
int vs, to;
slab = infra_create(cfg);
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
- sizeof(int), now, &vs, &to) );
+ (socklen_t)sizeof(int), now, &vs, &to) );
unit_assert( vs == 0 && to == 3000 );
unit_assert( infra_rtt_update(slab, (struct sockaddr_storage*)&one,
- sizeof(int), -1, now) );
+ (socklen_t)sizeof(int), -1, now) );
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
- sizeof(int), now, &vs, &to) );
+ (socklen_t)sizeof(int), now, &vs, &to) );
unit_assert( vs == 0 && to == 6000 );
unit_assert( infra_edns_update(slab, (struct sockaddr_storage*)&one,
- sizeof(int), -1, now) );
+ (socklen_t)sizeof(int), -1, now) );
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
- sizeof(int), now, &vs, &to) );
+ (socklen_t)sizeof(int), now, &vs, &to) );
unit_assert( vs == -1 && to == 6000 );
- now += HOST_TTL + 10;
+ now += cfg->host_ttl + 10;
unit_assert( infra_host(slab, (struct sockaddr_storage*)&one,
- sizeof(int), now, &vs, &to) );
+ (socklen_t)sizeof(int), now, &vs, &to) );
unit_assert( vs == 0 && to == 3000 );
unit_assert( infra_set_lame(slab, (struct sockaddr_storage*)&one,
- sizeof(int), zone, zonelen, now) );
+ (socklen_t)sizeof(int), zone, zonelen, now) );
unit_assert( (d=infra_lookup_host(slab, (struct sockaddr_storage*)&one,
- sizeof(int), 0, now, &k)) );
- unit_assert( d->ttl == now+HOST_TTL );
+ (socklen_t)sizeof(int), 0, now, &k)) );
+ unit_assert( d->ttl == now+cfg->host_ttl );
unit_assert( d->edns_version == 0 );
unit_assert( infra_lookup_lame(d, zone, zonelen, now) );
unit_assert( !infra_lookup_lame(d, zone, zonelen,
- now+HOST_LAME_TTL+10) );
+ now+cfg->lame_ttl+10) );
unit_assert( !infra_lookup_lame(d, (uint8_t*)"\000", 1, now) );
lock_rw_unlock(&k->entry.lock);
cfg->num_queries_per_thread = 1024;
cfg->rrset_cache_size = 4 * 1024 * 1024;
cfg->rrset_cache_slabs = 4;
+ cfg->host_ttl = 900;
+ cfg->lame_ttl = 900;
+ cfg->infra_cache_slabs = 4;
+ cfg->infra_cache_numhosts = 1000;
+ cfg->infra_cache_numlame = 1000;
if(!(cfg->fwd_address = strdup(""))) goto error_exit;
if(!(cfg->username = strdup(""))) goto error_exit;
if(!(cfg->chrootdir = strdup(""))) goto error_exit;
size_t rrset_cache_size;
/** slabs in the rrset cache */
size_t rrset_cache_slabs;
+ /** host cache ttl in seconds */
+ int host_ttl;
+ /** host is lame for a zone ttl, in seconds */
+ int lame_ttl;
+ /** number of slabs in the infra host cache */
+ size_t infra_cache_slabs;
+ /** max number of hosts in the infra cache */
+ size_t infra_cache_numhosts;
+ /** max number of lame zones per host in the infra cache */
+ size_t infra_cache_numlame;
/** forwarder address. string. If not NULL fwder mode is enabled. */
char* fwd_address;