[sr-dev] git:master: dns cache: dns_cache_rec_pref config var added

Miklos Tirpak miklos at iptel.org
Wed Jun 23 17:32:14 CEST 2010


Module: sip-router
Branch: master
Commit: 1b30ae44d71332d7e96221ee444a1aede2d3da01
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=1b30ae44d71332d7e96221ee444a1aede2d3da01

Author: Miklos Tirpak <miklos at iptel.org>
Committer: Miklos Tirpak <miklos at iptel.org>
Date:   Wed Jun 23 16:34:56 2010 +0200

dns cache: dns_cache_rec_pref config var added

The config variable, dns_cache_rec_pref, can be used
to set the DNS cache preference as follows:

	0 - do not check duplicates (default)
	1 - prefer old records
	2 - prefer new records
	3 - prefer records with longer lifetime

This variable is checked when a duplicated record is
tried to be inserted into the cache. For instance the
SRV query answer contains also an A record which is
already in the cache.
If the config var is not 0, then permanent entries
are always preferred.

Note: works only with #define CACHE_RELEVANT_RECS_ONLY
at the moment.

---

 NEWS        |    6 ++++++
 cfg_core.c  |    7 +++++++
 cfg_core.h  |    1 +
 dns_cache.c |   57 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/NEWS b/NEWS
index 0112243..5d691cb 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,7 @@ core:
     See dst_blacklist_udp_imask a.s.o (dst_blacklist_*_imask).
   - per message blacklist ignore masks
   - route() now supports rvalue expressions (e.g. route("test"+$i))
+  - support for permanent entries in the DNS cache.
 
 new config variables:
   - dst_blacklist_udp_imask - global blacklist events ignore mask for udp
@@ -27,6 +28,11 @@ new config variables:
    - dst_blacklist_tcp_imask - like dst_blacklist_udp_imask, but for tcp.
    - dst_blacklist_tls_imask - like dst_blacklist_tls_imask, but for tcp.
    - dst_blacklist_sctp_imask -like dst_blacklist_sctp_imask, but for tcp.
+   - dns_cache_rec_pref - DNS cache record preference:
+		0 - do not check duplicates (default)
+		1 - prefer old records
+		2 - prefer new records
+		3 - prefer records with longer lifetime
 
 modules:
    - blst: functions for ignoring blacklist events per message:
diff --git a/cfg_core.c b/cfg_core.c
index 101ba9f..d819dee 100644
--- a/cfg_core.c
+++ b/cfg_core.c
@@ -102,6 +102,7 @@ struct cfg_group_core default_core_cfg = {
 	DEFAULT_DNS_CACHE_MAX_TTL, /*!< maximum ttl */
 	DEFAULT_DNS_MAX_MEM, /*!< dns_cache_max_mem */
 	0, /*!< dns_cache_del_nonexp -- delete only expired entries by default */
+	0, /*!< dns_cache_rec_pref -- 0 by default, do not check the existing entries. */
 #endif
 #ifdef PKG_MALLOC
 	0, /*!< mem_dump_pkg */
@@ -206,6 +207,12 @@ cfg_def_t core_cfg_def[] = {
 	{"dns_cache_del_nonexp",	CFG_VAR_INT,	0, 1, 0, 0,
 		"allow deletion of non-expired records from the cache when "
 		"there is no more space left for new ones"},
+	{"dns_cache_rec_pref",	CFG_VAR_INT,	0, 3, 0, 0,
+		"DNS cache record preference: "
+		" 0 - do not check duplicates"
+		" 1 - prefer old records"
+		" 2 - prefer new records"
+		" 3 - prefer records with longer lifetime"},
 #endif
 #ifdef PKG_MALLOC
 	{"mem_dump_pkg",	CFG_VAR_INT,	0, 0, 0, mem_dump_pkg_cb,
diff --git a/cfg_core.h b/cfg_core.h
index 1e86692..c0d83c8 100644
--- a/cfg_core.h
+++ b/cfg_core.h
@@ -92,6 +92,7 @@ struct cfg_group_core {
 	unsigned int dns_cache_max_ttl;
 	unsigned int dns_cache_max_mem;
 	int dns_cache_del_nonexp;
+	int dns_cache_rec_pref;
 #endif
 #ifdef PKG_MALLOC
 	int mem_dump_pkg;
diff --git a/dns_cache.c b/dns_cache.c
index 2ec3d3e..adf2940 100644
--- a/dns_cache.c
+++ b/dns_cache.c
@@ -1874,10 +1874,14 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
 	struct ip_addr* ip;
 	str cname_val;
 	char name_buf[MAX_DNS_NAME];
+	struct dns_hash_entry* old;
+	str rec_name;
+	int add_record, h, err;
 
 	e=0;
 	l=0;
 	cname_val.s=0;
+	old = NULL;
 
 #ifdef USE_DNS_CACHE_STATS
 	if (dns_cache_stats)
@@ -1944,10 +1948,55 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
 			LOCK_DNS_HASH(); /* optimization */
 			for (r=l; r; r=t){
 				t=r->next;
-				dns_cache_add_unsafe(r); /* refcnt++ inside */
-				if (atomic_get(&r->refcnt)==0){
-					/* if cache adding failed and nobody else is interested
-					 * destroy this entry */
+				/* add the new record to the cache by default */
+				add_record = 1;
+				if (cfg_get(core, core_cfg, dns_cache_rec_pref) > 0) {
+					/* check whether there is an old record with the
+					 * same type in the cache */
+					rec_name.s = r->name;
+					rec_name.len = r->name_len;
+					old = _dns_hash_find(&rec_name, r->type, &h, &err);
+					if (old) {
+						if (old->type != r->type) {
+							/* probably CNAME found */
+							old = NULL;
+
+						} else if (old->ent_flags & DNS_FLAG_PERMANENT) {
+							/* never overwrite permanent entries */
+							add_record = 0;
+
+						} else if ((old->ent_flags & DNS_FLAG_BAD_NAME) == 0) {
+							/* Non-negative, non-permanent entry found with
+							 * the same type. */
+							add_record =
+								/* prefer new records */
+								((cfg_get(core, core_cfg, dns_cache_rec_pref) == 2)
+								/* prefer the record with the longer lifetime */
+								|| ((cfg_get(core, core_cfg, dns_cache_rec_pref) == 3)
+									&& TICKS_LT(old->expire, r->expire)));
+						}
+					}
+				}
+				if (add_record) {
+					dns_cache_add_unsafe(r); /* refcnt++ inside */
+					if (atomic_get(&r->refcnt)==0){
+						/* if cache adding failed and nobody else is interested
+						 * destroy this entry */
+						dns_destroy_entry(r);
+					}
+					if (old) {
+						_dns_hash_remove(old);
+						old = NULL;
+					}
+				} else {
+					if (old) {
+						if (r == e) {
+							/* this entry has to be returned */
+							e = old;
+							atomic_inc(&e->refcnt);
+						}
+						old = NULL;
+					}
 					dns_destroy_entry(r);
 				}
 			}




More information about the sr-dev mailing list