mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Random nameserver selection.
git-svn-id: file:///svn/unbound/trunk@361 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
d15e61a753
commit
e08155e86e
4 changed files with 89 additions and 36 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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*
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue