Browse Source

optimize dualstack selection feature

Nick Peng 6 years ago
parent
commit
76367847d1
3 changed files with 40 additions and 27 deletions
  1. 4 2
      src/dns_cache.c
  2. 4 3
      src/dns_cache.h
  3. 32 22
      src/dns_server.c

+ 4 - 2
src/dns_cache.c

@@ -66,7 +66,7 @@ static void _dns_cache_remove(struct dns_cache *dns_cache)
 	dns_cache_release(dns_cache);
 }
 
-int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len)
+int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, unsigned int speed)
 {
 	struct dns_cache *dns_cache = NULL;
 
@@ -90,6 +90,7 @@ int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_typ
 	dns_cache->qtype = qtype;
 	dns_cache->ttl = ttl;
 	dns_cache->del_pending = 0;
+	dns_cache->speed = speed;
 	time(&dns_cache->insert_time);
 	pthread_mutex_unlock(&dns_cache_head.lock);
 	if (qtype == DNS_T_A) {
@@ -121,7 +122,7 @@ errout:
 	return -1;
 }
 
-int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len)
+int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, unsigned int speed)
 {
 	uint32_t key = 0;
 	struct dns_cache *dns_cache = NULL;
@@ -155,6 +156,7 @@ int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type
 	dns_cache->ttl = ttl;
 	dns_cache->hitnum = 2;
 	dns_cache->del_pending = 0;
+	dns_cache->speed = speed;
 	atomic_set(&dns_cache->ref, 1);
 	time(&dns_cache->insert_time);
 	if (qtype == DNS_T_A) {

+ 4 - 3
src/dns_cache.h

@@ -19,7 +19,8 @@ struct dns_cache {
 	char domain[DNS_MAX_CNAME_LEN];
 	char cname[DNS_MAX_CNAME_LEN];
 	unsigned int cname_ttl;
-	unsigned int ttl;
+	unsigned int ttl;;
+	unsigned int speed;
 	int hitnum;
 	int del_pending;
 	time_t insert_time;
@@ -33,9 +34,9 @@ struct dns_cache {
 
 int dns_cache_init(int size);
 
-int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len);
+int dns_cache_replace(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, unsigned int speed);
 
-int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len);
+int dns_cache_insert(char *domain, char *cname, int cname_ttl, int ttl, dns_type_t qtype, unsigned char *addr, int addr_len, unsigned int speed);
 
 struct dns_cache *dns_cache_lookup(char *domain, dns_type_t qtype);
 

+ 32 - 22
src/dns_server.c

@@ -550,33 +550,16 @@ static int _dns_server_request_complete(struct dns_request *request)
 
 			/* if doing prefetch, update cache only */
 			if (request->prefetch) {
-				dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
+				dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4);
 			} else {
 				/* insert result to cache */
-				dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
+				dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4);
 			}
 
 			request->has_soa = 0;
 		}
 
 	} else if (request->qtype == DNS_T_AAAA) {
-		if (request->has_ipv4 && request->ping_ttl_v4 > 0) {
-			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]);
-
-			/* if ipv4 is fasting than ipv6, add ipv4 to cache, and return SOA for AAAA request */
-			if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 || request->ping_ttl_v6 < 0) {
-				tlog(TLOG_DEBUG, "Force IPV4 perfered.");
-				if (request->prefetch) {
-					dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN);
-				} else {
-					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);
-			}
-		}
-
 		if (request->has_ipv6) {
 			tlog(TLOG_INFO, "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],
@@ -589,15 +572,32 @@ static int _dns_server_request_complete(struct dns_request *request)
 
 			/* if doing prefetch, update cache only */
 			if (request->prefetch) {
-				dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN);
+				dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN, request->ping_ttl_v6);
 			} else {
 				/* insert result to cache */
-				dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN);
+				dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v6, DNS_T_AAAA, request->ipv6_addr, DNS_RR_AAAA_LEN, request->ping_ttl_v6);
 			}
+		}
 
+		if (request->has_ipv4 && request->ping_ttl_v4 > 0) {
+			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]);
+
+			/* if ipv4 is fasting than ipv6, add ipv4 to cache, and return SOA for AAAA request */
+			if ((request->ping_ttl_v4 + (dns_conf_dualstack_ip_selection_threshold * 10)) < request->ping_ttl_v6 || request->ping_ttl_v6 < 0) {
+				tlog(TLOG_DEBUG, "Force IPV4 perfered.");
+				if (request->prefetch) {
+					dns_cache_replace(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4);
+				} else {
+					dns_cache_insert(request->domain, cname, cname_ttl, request->ttl_v4, DNS_T_A, request->ipv4_addr, DNS_RR_A_LEN, request->ping_ttl_v4);
+				}
+
+				return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL);
+			}
 			request->has_ipv4 = 0;
-			request->has_soa = 0;
 		}
+
+		request->has_soa = 0;
 	}
 
 	if (request->has_soa) {
@@ -1445,6 +1445,16 @@ static int _dns_server_process_cache(struct dns_request *request, struct dns_pac
 		goto errout;
 	}
 
+	if (dns_conf_dualstack_ip_selection && request->qtype == DNS_T_AAAA) {
+		struct dns_cache *dns_cache_A = dns_cache_lookup(request->domain, DNS_T_A);
+		if (dns_cache_A) {
+			if ((dns_cache_A->speed + (dns_conf_dualstack_ip_selection_threshold * 10)) < dns_cache->speed || dns_cache->speed < 0) {
+				tlog(TLOG_DEBUG, "Force IPV4 perfered.");
+				return _dns_server_reply_SOA(DNS_RC_NOERROR, request, NULL);
+			}
+		}
+	}
+
 	/* Cache hits, returning results in the cache */
 	switch (request->qtype) {
 	case DNS_T_A: