From 50060590744410f5849f4a798c2a3f462bdd4959 Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Sat, 25 Jun 2022 20:24:27 +0800 Subject: [PATCH] cache: fix dns cache prefetch issue --- src/dns_cache.c | 46 ++++++++++++++++++++++++++++------------- src/dns_cache.h | 4 ++-- src/dns_conf.c | 15 ++++++++++++++ src/dns_server.c | 54 ++++++++++++++++++++++++++---------------------- 4 files changed, 78 insertions(+), 41 deletions(-) diff --git a/src/dns_cache.c b/src/dns_cache.c index d090b1f..78c7583 100644 --- a/src/dns_cache.c +++ b/src/dns_cache.c @@ -243,7 +243,8 @@ struct dns_cache_data *dns_cache_new_data_packet(uint32_t cache_flag, void *pack return (struct dns_cache_data *)cache_packet; } -int _dns_cache_replace(char *domain, int ttl, dns_type_t qtype, int speed, int inactive, struct dns_cache_data *cache_data) +int _dns_cache_replace(char *domain, int ttl, dns_type_t qtype, int speed, int inactive, + struct dns_cache_data *cache_data) { struct dns_cache *dns_cache = NULL; struct dns_cache_data *old_cache_data = NULL; @@ -521,10 +522,12 @@ void dns_cache_update(struct dns_cache *dns_cache) pthread_mutex_unlock(&dns_cache_head.lock); } -void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int ttl_inactive_pre, time_t *now) +void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int ttl_inactive_pre, + unsigned int max_callback_num, time_t *now) { struct dns_cache *dns_cache = NULL; struct dns_cache *tmp; + int callback_num = 0; int ttl = 0; LIST_HEAD(checklist); @@ -541,8 +544,12 @@ void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int continue; } - ttl = dns_cache->info.replace_time + dns_cache->info.ttl - *now; - if (ttl > 0) { + ttl = *now - dns_cache->info.replace_time; + if (ttl < ttl_inactive_pre || inactive_precallback == NULL) { + continue; + } + + if (callback_num >= max_callback_num) { continue; } @@ -551,12 +558,10 @@ void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int } /* If the TTL time is in the pre-timeout range, call callback function */ - if (inactive_precallback && ttl_inactive_pre < -ttl) { - list_add_tail(&dns_cache->check_list, &checklist); - dns_cache_get(dns_cache); - dns_cache->del_pending = 1; - continue; - } + dns_cache_get(dns_cache); + list_add_tail(&dns_cache->check_list, &checklist); + dns_cache->del_pending = 1; + callback_num++; } pthread_mutex_unlock(&dns_cache_head.lock); @@ -570,14 +575,19 @@ void _dns_cache_remove_expired_ttl(dns_cache_callback inactive_precallback, int } } -void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache_callback inactive_precallback, - int ttl_inactive_pre) +void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, unsigned int max_callback_num, + dns_cache_callback inactive_precallback, int ttl_inactive_pre) { struct dns_cache *dns_cache = NULL; struct dns_cache *tmp; time_t now; int ttl = 0; LIST_HEAD(checklist); + int callback_num = 0; + + if (max_callback_num <= 0) { + max_callback_num = -1; + } if (dns_cache_head.size <= 0) { return; @@ -590,10 +600,11 @@ void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache ttl = dns_cache->info.insert_time + dns_cache->info.ttl - now; if (ttl > 0 && ttl < ttl_pre) { /* If the TTL time is in the pre-timeout range, call callback function */ - if (precallback && dns_cache->del_pending == 0) { + if (precallback && dns_cache->del_pending == 0 && callback_num < max_callback_num) { list_add_tail(&dns_cache->check_list, &checklist); dns_cache_get(dns_cache); dns_cache->del_pending = 1; + callback_num++; continue; } } @@ -609,7 +620,7 @@ void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache pthread_mutex_unlock(&dns_cache_head.lock); if (dns_cache_head.enable_inactive && dns_cache_head.inactive_list_expired != 0) { - _dns_cache_remove_expired_ttl(inactive_precallback, ttl_inactive_pre, &now); + _dns_cache_remove_expired_ttl(inactive_precallback, ttl_inactive_pre, max_callback_num, &now); } list_for_each_entry_safe(dns_cache, tmp, &checklist, check_list) @@ -618,6 +629,7 @@ void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache if (precallback) { precallback(dns_cache); } + list_del(&dns_cache->check_list); dns_cache_release(dns_cache); } } @@ -695,11 +707,16 @@ int dns_cache_load(const char *file) { int fd = -1; int ret = 0; + size_t filesize; fd = open(file, O_RDONLY); if (fd < 0) { return 0; } + filesize = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + posix_fadvise(fd, 0, filesize, POSIX_FADV_WILLNEED | POSIX_FADV_SEQUENTIAL); + struct dns_cache_file cache_file; ret = read(fd, &cache_file, sizeof(cache_file)); if (ret != sizeof(cache_file)) { @@ -717,6 +734,7 @@ int dns_cache_load(const char *file) goto errout; } + tlog(TLOG_INFO, "load cache file %s, total %d records", file, cache_file.cache_number); if (_dns_cache_read_record(fd, cache_file.cache_number) != 0) { goto errout; } diff --git a/src/dns_cache.h b/src/dns_cache.h index 036f354..cbcaf05 100644 --- a/src/dns_cache.h +++ b/src/dns_cache.h @@ -143,8 +143,8 @@ void dns_cache_update(struct dns_cache *dns_cache); typedef void dns_cache_callback(struct dns_cache *dns_cache); -void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, dns_cache_callback inactive_precallback, - int ttl_inactive_pre); +void dns_cache_invalidate(dns_cache_callback precallback, int ttl_pre, unsigned int max_callback_num, + dns_cache_callback inactive_precallback, int ttl_inactive_pre); int dns_cache_get_ttl(struct dns_cache *dns_cache); diff --git a/src/dns_conf.c b/src/dns_conf.c index 80d7359..83b00be 100644 --- a/src/dns_conf.c +++ b/src/dns_conf.c @@ -913,6 +913,7 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type) char group_name[DNS_GROUP_NAME_LEN]; const char *group = NULL; unsigned int server_flag = 0; + int i = 0; /* clang-format off */ static struct option long_options[] = { @@ -940,6 +941,20 @@ static int _config_bind_ip(int argc, char *argv[], DNS_BIND_TYPE type) return 0; } + for (i = 0; i < dns_conf_bind_ip_num; i++) { + bind_ip = &dns_conf_bind_ip[i]; + if (bind_ip->type != type) { + continue; + } + + if (strncmp(bind_ip->ip, ip, DNS_MAX_IPLEN) != 0) { + continue; + } + + tlog(TLOG_WARN, "Bind server %s, type %d, already configured, skip.", ip, type); + return 0; + } + bind_ip = &dns_conf_bind_ip[index]; bind_ip->type = type; bind_ip->flags = 0; diff --git a/src/dns_server.c b/src/dns_server.c index 738b953..a26d8c8 100644 --- a/src/dns_server.c +++ b/src/dns_server.c @@ -56,6 +56,7 @@ #define SOCKET_PRIORITY (6) #define CACHE_AUTO_ENABLE_SIZE (1024 * 1024 * 128) #define EXPIRED_DOMAIN_PREFTCH_TIME (3600 * 8) +#define DNS_MAX_DOMAIN_REFETCH_NUM 16 #define RECV_ERROR_AGAIN 1 #define RECV_ERROR_OK 0 @@ -556,14 +557,14 @@ static void _dns_rrs_result_log(struct dns_server_post_context *context, struct } if (addr_map->addr_type == DNS_T_A) { - tlog(TLOG_INFO, "result: %s, id: %d, index: %d, rtt: %d, %d.%d.%d.%d", request->domain, request->id, - context->ip_num, addr_map->ping_time, addr_map->ip_addr[0], addr_map->ip_addr[1], addr_map->ip_addr[2], - addr_map->ip_addr[3]); + tlog(TLOG_INFO, "result: %s, id: %d, index: %d, rtt: %.1f ms, %d.%d.%d.%d", request->domain, request->id, + context->ip_num, ((float)addr_map->ping_time) / 10, addr_map->ip_addr[0], addr_map->ip_addr[1], + addr_map->ip_addr[2], addr_map->ip_addr[3]); } else if (addr_map->addr_type == DNS_T_AAAA) { tlog(TLOG_INFO, - "result: %s, id: %d, index: %d, rtt: %d, " + "result: %s, id: %d, index: %d, rtt: %.1f ms, " "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", - request->domain, request->id, context->ip_num, addr_map->ping_time, addr_map->ip_addr[0], + request->domain, request->id, context->ip_num, ((float)addr_map->ping_time) / 10, addr_map->ip_addr[0], addr_map->ip_addr[1], addr_map->ip_addr[2], addr_map->ip_addr[3], addr_map->ip_addr[4], addr_map->ip_addr[5], addr_map->ip_addr[6], addr_map->ip_addr[7], addr_map->ip_addr[8], addr_map->ip_addr[9], addr_map->ip_addr[10], addr_map->ip_addr[11], addr_map->ip_addr[12], @@ -689,7 +690,7 @@ static int _dns_add_rrs(struct dns_server_post_context *context) context->ip_num++; if (context->qtype == DNS_T_A) { ret |= dns_add_A(context->packet, DNS_RRS_AN, domain, request->ip_ttl, request->ip_addr); - tlog(TLOG_DEBUG, "result: %s, rtt: %d, %d.%d.%d.%d", request->domain, request->ping_time, + tlog(TLOG_DEBUG, "result: %s, rtt: %.1f ms, %d.%d.%d.%d", request->domain, ((float)request->ping_time) / 10, request->ip_addr[0], request->ip_addr[1], request->ip_addr[2], request->ip_addr[3]); } @@ -697,13 +698,13 @@ static int _dns_add_rrs(struct dns_server_post_context *context) if (context->qtype == DNS_T_AAAA) { ret |= dns_add_AAAA(context->packet, DNS_RRS_AN, domain, request->ip_ttl, request->ip_addr); tlog(TLOG_DEBUG, - "result: %s, rtt: %d, " + "result: %s, rtt: %.1f ms, " "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", - request->domain, request->ping_time, request->ip_addr[0], request->ip_addr[1], request->ip_addr[2], - request->ip_addr[3], request->ip_addr[4], request->ip_addr[5], request->ip_addr[6], - request->ip_addr[7], request->ip_addr[8], request->ip_addr[9], request->ip_addr[10], - request->ip_addr[11], request->ip_addr[12], request->ip_addr[13], request->ip_addr[14], - request->ip_addr[15]); + request->domain, ((float)request->ping_time) / 10, request->ip_addr[0], request->ip_addr[1], + request->ip_addr[2], request->ip_addr[3], request->ip_addr[4], request->ip_addr[5], + request->ip_addr[6], request->ip_addr[7], request->ip_addr[8], request->ip_addr[9], + request->ip_addr[10], request->ip_addr[11], request->ip_addr[12], request->ip_addr[13], + request->ip_addr[14], request->ip_addr[15]); } } @@ -1539,18 +1540,18 @@ static int _dns_server_request_complete(struct dns_request *request) tlog(TLOG_INFO, "result: %s, qtype: %d, SOA", request->domain, request->qtype); } else { if (request->qtype == DNS_T_A) { - tlog(TLOG_INFO, "result: %s, qtype: %d, rtt: %d, %d.%d.%d.%d", request->domain, request->qtype, - request->ping_time, request->ip_addr[0], request->ip_addr[1], request->ip_addr[2], + tlog(TLOG_INFO, "result: %s, qtype: %d, rtt: %.1f ms, %d.%d.%d.%d", request->domain, request->qtype, + ((float)request->ping_time) / 10, request->ip_addr[0], request->ip_addr[1], request->ip_addr[2], request->ip_addr[3]); } else if (request->qtype == DNS_T_AAAA) { tlog(TLOG_INFO, - "result: %s, qtype: %d, rtt: %d, " + "result: %s, qtype: %d, rtt: %.1f ms, " "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x", - request->domain, request->qtype, request->ping_time, request->ip_addr[0], request->ip_addr[1], - request->ip_addr[2], request->ip_addr[3], request->ip_addr[4], request->ip_addr[5], - request->ip_addr[6], request->ip_addr[7], request->ip_addr[8], request->ip_addr[9], - request->ip_addr[10], request->ip_addr[11], request->ip_addr[12], request->ip_addr[13], - request->ip_addr[14], request->ip_addr[15]); + request->domain, request->qtype, ((float)request->ping_time) / 10, request->ip_addr[0], + request->ip_addr[1], request->ip_addr[2], request->ip_addr[3], request->ip_addr[4], + request->ip_addr[5], request->ip_addr[6], request->ip_addr[7], request->ip_addr[8], + request->ip_addr[9], request->ip_addr[10], request->ip_addr[11], request->ip_addr[12], + request->ip_addr[13], request->ip_addr[14], request->ip_addr[15]); } } @@ -2649,7 +2650,7 @@ void _dns_server_query_end(struct dns_request *request) if (request->dualstack_selection_has_ip && request->dualstack_selection_ping_time > 0) { goto out; } - + request->has_ping_result = 1; _dns_server_request_complete(request); } @@ -4560,7 +4561,7 @@ static void _dns_server_period_run_second(void) } if (now - 180 > last) { - dns_cache_invalidate(NULL, 0, NULL, 0); + dns_cache_invalidate(NULL, 0, 0, NULL, 0); tlog(TLOG_WARN, "Service paused for 180s, force invalidate cache."); } @@ -4578,12 +4579,13 @@ static void _dns_server_period_run_second(void) prefetch_time = EXPIRED_DOMAIN_PREFTCH_TIME; } } - dns_cache_invalidate(NULL, 0, _dns_server_prefetch_expired_domain, prefetch_time); + dns_cache_invalidate(NULL, 0, DNS_MAX_DOMAIN_REFETCH_NUM, _dns_server_prefetch_expired_domain, + prefetch_time); } else { - dns_cache_invalidate(_dns_server_prefetch_domain, 3, NULL, 0); + dns_cache_invalidate(_dns_server_prefetch_domain, 3, DNS_MAX_DOMAIN_REFETCH_NUM, NULL, 0); } } else { - dns_cache_invalidate(NULL, 0, NULL, 0); + dns_cache_invalidate(NULL, 0, 0, NULL, 0); } } @@ -4806,6 +4808,8 @@ static int _dns_create_socket(const char *host_ip, int type) } } + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + freeaddrinfo(gai); return fd;