android dns之dns服务器可用性机制,成功率低于门限则惩罚抑制(一)
1 dns服务器可用性检测
1.1 send dns请求前,所有dns server是否可用,可用性结果保存到usable_servers[]。
bionic\libc\dns\resolv\res_send.c
int
res_nsend(res_state statp,
const u_char *buf, int buflen, u_char *ans, int anssiz)
{
......
bool usable_servers[MAXNS];
android_net_res_stats_get_usable_servers(¶ms, stats, statp->nscount,
usable_servers);
for (ns = 0; ns < statp->nscount; ns++) {
if (!usable_servers[ns]) continue;
1.2 通过_res_stats_usable_server遍历检查每个DNS server的可用性。如果检测为都不可用,则调整为都可用。
bionic\libc\dns\resolv\res_stats.c
android_net_res_stats_get_usable_servers(const struct __res_params* params,
struct __res_stats stats[], int nscount, bool usable_servers[]) {
unsigned usable_servers_found = 0;
for (int ns = 0; ns < nscount; ns++) {
bool usable = _res_stats_usable_server(params, &stats[ns]);
if (usable) {
++usable_servers_found;
}
usable_servers[ns] = usable;
}
// If there are no usable servers, consider all of them usable.
// TODO: Explore other possibilities, such as enabling only the best N servers, etc.
if (usable_servers_found == 0) {
for (int ns = 0; ns < nscount; ns++) {
usable_servers[ns] = true;
}
}
}
1.3 _res_stats_usable_server检查
1.3.1 dns全局cache链_res_cache_list,一张网络netid对应一个链节点Cache,含该网络的dns统计__res_stats(最大4个NS的统计)
// Head of the list of caches. Protected by _res_cache_list_lock.
static struct resolv_cache_info _res_cache_list;
struct resolv_cache_info {
unsigned netid;
Cache* cache;
struct resolv_cache_info* next;
int nscount;
char* nameservers[MAXNS];
struct addrinfo* nsaddrinfo[MAXNS];
int revision_id; // # times the nameservers have been replaced
struct __res_params params;
struct __res_stats nsstats[MAXNS];
char defdname[MAXDNSRCHPATH];
int dnsrch_offset[MAXDNSRCH+1]; // offsets into defdname
/*AR000AT6PU liuheng 00308202 20180720 begin */
bool isipv6optimizationopen;
int ipv6timeout;
unsigned iptype;// ipaddrtype ipv4,ipv6 or ipv4v6
int servicetype;
unsigned ipv6domainblacklistcount;
char* domainblacklist[IPV6MAXBLACKLISTLEN];
/*AR000AT6PU liuheng 00308202 20180720 end */
};
1.3.1 dns参数(含惩罚门限)
1.3.1.1 成功率门限75% SUCCESS_THRESHOLD 75
1.3.1.2 默认sample有效期1800秒 #define NSSAMPLE_VALIDITY 1800
/* Hard-coded defines */
#define MAXNS 4 /* max # name servers we'll track */
#define MAXDNSRCH 6 /* max # domains in search path */
#define MAXDNSRCHPATH 256 /* max length of domain search paths */
#define MAXNSSAMPLES 64 /* max # samples to store per server */
/* Defaults used for initializing __res_params */
#define SUCCESS_THRESHOLD 75 /* if successes * 100 / total_samples is less than
* this value, the server is considered failing
*/
#define NSSAMPLE_VALIDITY 1800 /* Sample validity in seconds.
* Set to -1 to disable skipping failing
* servers.
*/
/* If EDNS0_PADDING is defined, queries will be padded to a multiple of this length
when EDNS0 is active. */
#define EDNS0_PADDING 128
/* per-netid configuration parameters passed from netd to the resolver */
struct __res_params {
uint16_t sample_validity; // sample lifetime in s
// threshold of success / total samples below which a server is considered broken
uint8_t success_threshold; // 0: disable, value / 100 otherwise
uint8_t min_samples; // min # samples needed for statistics to be considered meaningful
uint8_t max_samples; // max # samples taken into account for statistics
};
1.3.2 dns server可用性统计参数
bionic\libc\dns\include\resolv_stats.h
__res_stats,针对一个dns server的统计,记录了最近sample_count个dns请求记录的时延等结果
#define RCODE_INTERNAL_ERROR 254
#define RCODE_TIMEOUT 255
/*
* Resolver reachability statistics and run-time parameters.
*/
struct __res_sample {
time_t at; // time in s at which the sample was recorded
uint16_t rtt; // round-trip time in ms
uint8_t rcode; // the DNS rcode or RCODE_XXX defined above
};
struct __res_stats {
// Stats of the last <sample_count> queries.
struct __res_sample samples[MAXNSSAMPLES];
// The number of samples stored.
uint8_t sample_count;
// The next sample to modify.
uint8_t sample_next; //下一个sample将存放到数组里的索引
};