optimize for selecting best ip address

Signed-off-by: Nick Peng <pymumu@gmail.com>
This commit is contained in:
Nick Peng
2019-01-17 21:19:59 +08:00
parent 73d4e9f822
commit dd4372a961
2 changed files with 40 additions and 16 deletions

View File

@@ -2,10 +2,10 @@
BIN=smartdns
OBJS_LIB=lib/rbtree.o lib/art.o lib/bitops.o lib/radix.o lib/conf.o
OBJS=smartdns.o fast_ping.o dns_client.o dns_server.o dns.o util.o tlog.o dns_conf.o dns_cache.o $(OBJS_LIB)
CFLAGS +=-O2 -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing
CFLAGS +=-O2 -g -Wall -Wstrict-prototypes -fno-omit-frame-pointer -Wstrict-aliasing
CFLAGS +=-Iinclude
CFLAGS += -DBASE_FILE_NAME=\"$(notdir $<)\"
CXXFLAGS=-O2 -Wall -std=c++11
CXXFLAGS=-O2 -g -Wall -std=c++11
CXXFLAGS +=-Iinclude
LDFLAGS += -lpthread -lssl -lcrypto

View File

@@ -93,6 +93,7 @@ struct dns_server {
struct dns_ip_address {
struct hlist_node node;
int hitnum;
unsigned long recv_tick;
dns_type_t addr_type;
union {
unsigned char ipv4_addr[DNS_RR_A_LEN];
@@ -540,13 +541,14 @@ int _dns_server_request_complete(struct dns_request *request)
tlog(TLOG_INFO, "result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
request->ipv4_addr[2], request->ipv4_addr[3]);
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_AAAA, request->ipv4_addr, DNS_RR_A_LEN);
if (((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10) < request->ping_ttl_v6) && (request->ping_ttl_v4 > 0)) ||
(request->ping_ttl_v6 == -1)) {
((request->ping_ttl_v6 == -1) && (request->ping_ttl_v4 > 0))) {
tlog(TLOG_DEBUG, "Force IPV4 perfered.");
dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL);
}
request->has_ipv4 = 0;
}
if (request->has_ipv6) {
@@ -596,12 +598,15 @@ void _dns_server_request_remove(struct dns_request *request)
_dns_server_request_release(request);
}
void _dns_server_select_maxhit_ipaddress(struct dns_request *request)
void _dns_server_select_possible_ipaddress(struct dns_request *request)
{
int maxhit = 0;
int bucket = 0;
unsigned long max_recv_tick = 0;
struct dns_ip_address *addr_map;
struct dns_ip_address *maxhit_addr_map = NULL;
struct dns_ip_address *last_recv_addr_map = NULL;
struct dns_ip_address *selected_addr_map = NULL;
struct hlist_node *tmp;
if (atomic_read(&request->notified) > 0) {
@@ -614,27 +619,42 @@ void _dns_server_select_maxhit_ipaddress(struct dns_request *request)
continue;
}
if (addr_map->hitnum <= maxhit) {
continue;
if (addr_map->recv_tick - request->send_tick > max_recv_tick) {
max_recv_tick = addr_map->recv_tick - request->send_tick;
last_recv_addr_map = addr_map;
}
maxhit = addr_map->hitnum;
maxhit_addr_map = addr_map;
if (addr_map->hitnum > maxhit) {
maxhit = addr_map->hitnum;
maxhit_addr_map = addr_map;
}
}
if (maxhit_addr_map == NULL || maxhit == 1) {
if (maxhit_addr_map && maxhit > 1) {
selected_addr_map = maxhit_addr_map;
} else if (last_recv_addr_map) {
selected_addr_map = last_recv_addr_map;
}
if (selected_addr_map == NULL) {
return;
}
tlog(TLOG_DEBUG, "select best ip address, %s", request->domain);
switch (request->qtype) {
case DNS_T_A: {
memcpy(request->ipv4_addr, maxhit_addr_map->ipv4_addr, DNS_RR_A_LEN);
memcpy(request->ipv4_addr, selected_addr_map->ipv4_addr, DNS_RR_A_LEN);
request->ttl_v4 = DNS_SERVER_TMOUT_TTL;
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %d.%d.%d.%d\n", request->domain, request->rcode, request->ipv4_addr[0], request->ipv4_addr[1],
request->ipv4_addr[2], request->ipv4_addr[3]);
} break;
case DNS_T_AAAA: {
memcpy(request->ipv6_addr, maxhit_addr_map->ipv6_addr, DNS_RR_AAAA_LEN);
memcpy(request->ipv6_addr, selected_addr_map->ipv6_addr, DNS_RR_AAAA_LEN);
request->ttl_v6 = DNS_SERVER_TMOUT_TTL;
tlog(TLOG_DEBUG, "possible result: %s, rcode: %d, %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", request->domain, request->rcode,
request->ipv6_addr[0], request->ipv6_addr[1], request->ipv6_addr[2], request->ipv6_addr[3], request->ipv6_addr[4], request->ipv6_addr[5],
request->ipv6_addr[6], request->ipv6_addr[7], request->ipv6_addr[8], request->ipv6_addr[9], request->ipv6_addr[10], request->ipv6_addr[11],
request->ipv6_addr[12], request->ipv6_addr[13], request->ipv6_addr[14], request->ipv6_addr[15]);
} break;
default:
break;
@@ -661,7 +681,7 @@ void _dns_server_request_release(struct dns_request *request)
pthread_mutex_unlock(&server.request_list_lock);
/* Select max hit ip address, and return to client */
_dns_server_select_maxhit_ipaddress(request);
_dns_server_select_possible_ipaddress(request);
_dns_server_request_complete(request);
hash_for_each_safe(request->ip_map, bucket, tmp, addr_map, node)
@@ -698,6 +718,8 @@ void _dns_server_ping_result(struct ping_host_struct *ping_host, const char *hos
_dns_server_request_release(request);
fast_ping_stop(ping_host);
return;
} else if (result == PING_RESULT_TIMEOUT) {
return;
}
unsigned int rtt = tv->tv_sec * 10000 + tv->tv_usec / 100;
@@ -785,12 +807,14 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr,
if (addr_type == DNS_T_A) {
if (memcmp(addr_map->ipv4_addr, addr, addr_len) == 0) {
addr_map->hitnum++;
addr_map->recv_tick = get_tick_count();
pthread_mutex_unlock(&request->ip_map_lock);
return -1;
}
} else if (addr_type == DNS_T_AAAA) {
if (memcmp(addr_map->ipv6_addr, addr, addr_len) == 0) {
addr_map->hitnum++;
addr_map->recv_tick = get_tick_count();
pthread_mutex_unlock(&request->ip_map_lock);
return -1;
}
@@ -807,6 +831,7 @@ int _dns_ip_address_check_add(struct dns_request *request, unsigned char *addr,
addr_map->addr_type = addr_type;
addr_map->hitnum = 1;
addr_map->recv_tick = get_tick_count();
memcpy(addr_map->addr, addr, addr_len);
hash_add(request->ip_map, &addr_map->node, key);
pthread_mutex_unlock(&request->ip_map_lock);
@@ -1797,7 +1822,6 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
{
struct dns_ip_address *addr_map;
int bucket = 0;
char name[DNS_MAX_CNAME_LEN] = {0};
char ip[DNS_MAX_CNAME_LEN] = {0};
if (request->has_ping_result) {
@@ -1821,7 +1845,7 @@ void _dns_server_tcp_ping_check(struct dns_request *request)
} break;
case DNS_T_AAAA: {
_dns_server_request_get(request);
sprintf(name, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]:80", addr_map->ipv6_addr[0], addr_map->ipv6_addr[1],
sprintf(ip, "[%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x]:80", addr_map->ipv6_addr[0], addr_map->ipv6_addr[1],
addr_map->ipv6_addr[2], addr_map->ipv6_addr[3], addr_map->ipv6_addr[4], addr_map->ipv6_addr[5], addr_map->ipv6_addr[6],
addr_map->ipv6_addr[7], addr_map->ipv6_addr[8], addr_map->ipv6_addr[9], addr_map->ipv6_addr[10], addr_map->ipv6_addr[11],
addr_map->ipv6_addr[12], addr_map->ipv6_addr[13], addr_map->ipv6_addr[14], addr_map->ipv6_addr[15]);