Random nameserver selection.

git-svn-id: file:///svn/unbound/trunk@361 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-06-04 09:57:02 +00:00
parent d15e61a753
commit e08155e86e
4 changed files with 89 additions and 36 deletions

View file

@ -763,6 +763,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker->env = *worker->daemon->env; worker->env = *worker->daemon->env;
worker->env.worker = worker; worker->env.worker = worker;
worker->env.alloc = &worker->alloc; worker->env.alloc = &worker->alloc;
worker->env.rnd = worker->rndstate;
return 1; return 1;
} }

View file

@ -1,3 +1,6 @@
4 June 2007: Wouter
- random selection of equally preferred nameserver targets.
1 June 2007: Wouter 1 June 2007: Wouter
- normalize incoming messages. Like unbound-java, with CNAME chain - normalize incoming messages. Like unbound-java, with CNAME chain
checked, DNAME checked, CNAME's synthesized, glue checked. checked, DNAME checked, CNAME's synthesized, glue checked.

View file

@ -53,7 +53,8 @@
#include "util/config_file.h" #include "util/config_file.h"
#include "util/region-allocator.h" #include "util/region-allocator.h"
#include "util/data/msgparse.h" #include "util/data/msgparse.h"
#include "util/random.h"
int int
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
{ {
@ -97,7 +98,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
/** filter out unsuitable targets, return rtt or -1 */ /** filter out unsuitable targets, return rtt or -1 */
static int static int
iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
struct delegpt_addr* a, uint8_t* name, size_t namelen, time_t now) uint8_t* name, size_t namelen, time_t now, struct delegpt_addr* a)
{ {
int rtt; int rtt;
int lame; int lame;
@ -116,43 +117,90 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
return UNKNOWN_SERVER_NICENESS; return UNKNOWN_SERVER_NICENESS;
} }
struct delegpt_addr* iter_server_selection(struct iter_env* iter_env, /** filter the addres list, putting best targets at front,
* returns number of best targets (or 0, no suitable targets) */
static int
iter_filter_order(struct iter_env* iter_env, struct module_env* env,
uint8_t* name, size_t namelen, time_t now, struct delegpt* dp)
{
int got_num = 0, got_rtt = 0, thisrtt, swap_to_front;
struct delegpt_addr* a, *n, *prev=NULL;
a = dp->result_list;
while(a) {
/* filter out unsuitable targets */
thisrtt = iter_filter_unsuitable(iter_env, env, name, namelen,
now, a);
if(thisrtt == -1) {
prev = a;
a = a->next_result;
continue;
}
/* classify the server address and determine what to do */
swap_to_front = 0;
if(got_num == 0) {
got_rtt = thisrtt;
got_num = 1;
swap_to_front = 1;
} else if(thisrtt == got_rtt) {
got_num++;
swap_to_front = 1;
} else if(thisrtt < got_rtt) {
got_rtt = thisrtt;
got_num = 1; /* start back at count of 1 */
swap_to_front = 1;
}
/* swap to front if necessary, or move to next result */
if(swap_to_front && prev) {
n = a->next_result;
prev->next_result = n;
a->next_result = dp->result_list;
dp->result_list = a;
a = n;
} else {
prev = a;
a = a->next_result;
}
}
return got_num;
}
struct delegpt_addr*
iter_server_selection(struct iter_env* iter_env,
struct module_env* env, struct delegpt* dp, struct module_env* env, struct delegpt* dp,
uint8_t* name, size_t namelen) uint8_t* name, size_t namelen)
{ {
int got_one = 0, got_rtt = 0;
struct delegpt_addr* got = NULL, *got_prev = NULL, *a, *prev = NULL;
time_t now = time(NULL); time_t now = time(NULL);
int sel;
struct delegpt_addr* a, *prev;
int num = iter_filter_order(iter_env, env, name, namelen, now, dp);
for(a = dp->result_list; a; a = a->next_result) { if(num == 0)
/* filter out unsuitable targets */ return NULL;
int thisrtt = iter_filter_unsuitable(iter_env, env, a, name, if(num == 1) {
namelen, now); a = dp->result_list;
if(thisrtt == -1) { dp->result_list = a->next_result;
prev = a; return a;
continue; }
} /* randomly select a target from the list */
if(!got_one) { log_assert(num > 1);
got_rtt = thisrtt; /* we do not need secure random numbers here, but
got = a; * we do need it to be threadsafe, so we use this */
got_prev = prev; sel = ub_random(env->rnd) % num;
got_one = 1; a = dp->result_list;
} else { prev = NULL;
if(thisrtt < got_rtt) { while(sel > 0 && a) {
got_rtt = thisrtt;
got = a;
got_prev = prev;
}
}
prev = a; prev = a;
a = a->next_result;
sel--;
} }
if(got) { if(!a) /* robustness */
/* remove it from list */ return NULL;
if(got_prev) /* remove it from list */
got_prev->next_result = got->next_result; if(prev)
else dp->result_list = got->next_result; prev->next_result = a->next_result;
} else dp->result_list = a->next_result;
return got; return a;
} }
struct dns_msg* struct dns_msg*

View file

@ -53,6 +53,7 @@ struct edns_data;
struct region; struct region;
struct worker; struct worker;
struct module_qstate; struct module_qstate;
struct ub_randstate;
/** Maximum number of modules in operation */ /** Maximum number of modules in operation */
#define MAX_MODULE 2 #define MAX_MODULE 2
@ -116,12 +117,12 @@ struct module_env {
struct sockaddr_storage* addr, socklen_t addrlen, struct sockaddr_storage* addr, socklen_t addrlen,
struct module_qstate* q); struct module_qstate* q);
/** create a subquery. operate should then return with wait_subq */
/** allocation service */
struct alloc_cache* alloc;
/** internal data for daemon - worker thread. */ /** internal data for daemon - worker thread. */
struct worker* worker; struct worker* worker;
/** allocation service */
struct alloc_cache* alloc;
/** random table to generate random numbers */
struct ub_randstate* rnd;
/** module specific data. indexed by module id. */ /** module specific data. indexed by module id. */
void* modinfo[MAX_MODULE]; void* modinfo[MAX_MODULE];
}; };