DNS watchdog support implementation: a SER module or an external application can...
authorMiklos Tirpak <miklos@iptel.org>
Thu, 26 Jul 2007 11:18:34 +0000 (11:18 +0000)
committerMiklos Tirpak <miklos@iptel.org>
Thu, 26 Jul 2007 11:18:34 +0000 (11:18 +0000)
are down. No DNS query is performed in this case, and even expired entries are used from the cache. Use
dns_set_server_state() function from modules or the dns.set_server_state RPC command to set the sate of the DNS
servers.

The feature is desabled by default, enable it with -DDNS_WATCHDOG_SUPPORT (required DNS cache enabled)

Makefile.defs
core_cmd.c
dns_cache.c
dns_cache.h
version.h

index b3e4057..afb5737 100644 (file)
@@ -60,6 +60,7 @@
 #  2007-05-26  changed darwin module link flags (instead of -bundle_loader ser
 #               -flat_namespace -undefined suppress) (andrei)
 #  2007-07-07  added HAVE_SCHED_SETSCHEDULER for linux (andrei)
+#  2007-07-18  added DNS_WATCHDOG_SUPPORT (Miklos)
 
 # check if already included/exported
 
@@ -403,6 +404,11 @@ endif
 #         unsafe)
 # -DUSE_NAPTR
 #               turns on naptr support (but must be also enabled from the config)
+# -DDNS_WATCHDOG_SUPPORT
+#              turns on DNS watchdog support which can be used to inform the
+#              core that the DNS servers are down. No DNS query is performed
+#              when the servers are unreachable, and even expired resource
+#              records are used from the cache. (requires external watchdog)
 
 # Sometimes is needes correct non-quoted $OS. HACK: gcc translates known OS to number ('linux'), so there is added underscore
 
@@ -423,6 +429,7 @@ DEFS+= $(extra_defs) \
         -DUSE_DNS_FAILOVER \
         -DUSE_DST_BLACKLIST \
         -DUSE_NAPTR \
+        #-DDNS_WATCHDOG_SUPPORT \
         #-DLL_MALLOC \
         #-DSF_MALLOC \
         #-DDL_MALLOC \
index 5421955..1836ad4 100644 (file)
@@ -57,7 +57,17 @@ static const char* dns_cache_debug_all_doc[] = {
        "complete dns debug  dump",    /* Documentation string */
        0                              /* Method signature(s) */
 };
-#endif
+
+#ifdef DNS_WATCHDOG_SUPPORT
+void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
+
+static const char* dns_set_server_state_doc[] = {
+       "sets the state of the DNS servers " \
+       "(0: all the servers are down, 1: at least one server is up)",    /* Documentation string */
+       0                              /* Method signature(s) */
+};
+#endif /* DNS_WATCHDOG_SUPPORT */
+#endif /* USE_DNS_CACHE */
 #ifdef USE_DST_BLACKLIST
 void dst_blst_debug(rpc_t* rpc, void* ctx);
 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
@@ -469,6 +479,9 @@ rpc_export_t core_rpc_methods[] = {
        {"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,     0 },
        {"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,        0 },
        {"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,        0     },
+#ifdef DNS_WATCHDOG_SUPPORT
+       {"dns.set_server_state",   dns_set_server_state_rpc, dns_set_server_state_doc, 0 },
+#endif
 #endif
 #ifdef USE_DST_BLACKLIST
        {"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,     0 },
index 2279092..de435be 100644 (file)
@@ -33,6 +33,8 @@
  *  2007-06-14  dns iterate through A & AAAA records fix (andrei)
  *  2007-06-15  srv rr weight based load balancing support (andrei)
  *  2007-06-16  naptr support (andrei)
+ *  2008-07-18  DNS watchdog support -- can be used to inform the core
+ *              that the DNS servers are down (Miklos)
  */
 
 #ifdef USE_DNS_CACHE
@@ -112,6 +114,10 @@ static struct dns_hash_head* dns_hash=0;
 
 static struct timer_ln* dns_timer_h=0;
 
+#ifdef DNS_WATCHDOG_SUPPORT
+static atomic_t *dns_servers_up = NULL;
+#endif
+
 
 
 static const char* dns_str_errors[]={
@@ -192,6 +198,11 @@ inline static int dns_cache_free_mem(unsigned int target, int expired_only);
 
 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
 {
+#ifdef DNS_WATCHDOG_SUPPORT
+       /* do not clean the hash table if the servers are down */
+       if (atomic_get(dns_servers_up) == 0)
+               return (ticks_t)(-1);
+#endif
        if (*dns_cache_mem_used>12*(dns_cache_max_mem/16)){ /* ~ 75% used */
                dns_cache_free_mem(dns_cache_max_mem/2, 1); 
        }else{
@@ -210,6 +221,12 @@ void destroy_dns_cache()
                timer_free(dns_timer_h);
                dns_timer_h=0;
        }
+#ifdef DNS_WATCHDOG_SUPPORT
+       if (dns_servers_up){
+               shm_free(dns_servers_up);
+               dns_servers_up=0;
+       }
+#endif
        if (dns_hash_lock){
                lock_destroy(dns_hash_lock);
                lock_dealloc(dns_hash_lock);
@@ -277,6 +294,15 @@ int init_dns_cache()
                ret=-1;
                goto error;
        }
+
+#ifdef DNS_WATCHDOG_SUPPORT
+       dns_servers_up=shm_malloc(sizeof(atomic_t));
+       if (dns_servers_up==0){
+               ret=E_OUT_OF_MEM;
+               goto error;
+       }
+       atomic_set(dns_servers_up, 1);
+#endif
        
        /* fix options */
        dns_cache_max_mem<<=10; /* Kb */ /* TODO: test with 0 */
@@ -413,6 +439,11 @@ inline static struct dns_hash_entry* _dns_hash_find(str* name, int type,
        ticks_t now;
        int cname_chain;
        str cname;
+#ifdef DNS_WATCHDOG_SUPPORT
+       int servers_up;
+
+       servers_up = atomic_get(dns_servers_up);
+#endif
        
        cname_chain=0;
        ret=0;
@@ -425,8 +456,14 @@ again:
                                                                                                name->len, type, *h);
 #endif
        clist_foreach_safe(&dns_hash[*h], e, tmp, next){
-               /* automatically remove expired elements */
-               if ((s_ticks_t)(now-e->expire)>=0){
+               if (
+#ifdef DNS_WATCHDOG_SUPPORT
+                       /* remove expired elements only when the dns servers are up */
+                       servers_up &&
+#endif
+                       /* automatically remove expired elements */
+                       ((s_ticks_t)(now-e->expire)>=0)
+               ) {
                                _dns_hash_remove(e);
                }else if ((e->type==type) && (e->name_len==name->len) &&
                        (strncasecmp(e->name, name->s, e->name_len)==0)){
@@ -1476,6 +1513,10 @@ inline static struct dns_hash_entry* dns_cache_do_request(str* name, int type)
                                goto end;/* we do not cache obvious stuff */
                }
        }
+#ifdef DNS_WATCHDOG_SUPPORT
+       if (atomic_get(dns_servers_up)==0)
+               goto end; /* the servers are down, needless to perform the query */
+#endif
        if (name->len>=MAX_DNS_NAME){
                LOG(L_ERR, "ERROR: dns_cache_do_request: name too long (%d chars)\n",
                                        name->len);
@@ -1660,11 +1701,22 @@ inline static struct dns_rr* dns_entry_get_rr(  struct dns_hash_entry* e,
        struct dns_rr* rr;
        int n;
        int flags;
+#ifdef DNS_WATCHDOG_SUPPORT
+       int servers_up;
+
+       servers_up = atomic_get(dns_servers_up);
+#endif
        
        flags=0;
        for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
        for(;rr;rr=rr->next){
-               if ((s_ticks_t)(now-e->expire)>=0) /* expired entry */
+               if (
+#ifdef DNS_WATCHDOG_SUPPORT
+                       /* check the expiration time only when the servers are up */
+                       servers_up &&
+#endif
+                       ((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
+               )
                        continue;
                if (rr->err_flags){ /* bad rr */
                        continue;
@@ -1741,6 +1793,11 @@ inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
                        unsigned r_sum;
                        struct dns_rr* rr;
                        }r_sums[MAX_SRV_GRP_IDX];
+#ifdef DNS_WATCHDOG_SUPPORT
+       int servers_up;
+
+       servers_up = atomic_get(dns_servers_up);
+#endif
        
        rand_w=0;
        for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
@@ -1755,7 +1812,12 @@ retry:
        found=0;
        for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
                                                (idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
-               if ( ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */ ||
+               if ((
+#ifdef DNS_WATCHDOG_SUPPORT
+                       /* check the expiration time only when the servers are up */
+                       servers_up &&
+#endif
+                       ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
                                (rr->err_flags) /* bad rr */ ||
                                (srv_marked(tried, idx)) ) /* already tried */{
                        r_sums[idx].r_sum=0; /* 0 sum, to skip over it */
@@ -2939,6 +3001,16 @@ int dns_srv_get_ip(str* name, struct ip_addr* ip, unsigned short* port,
 }
 
 
+#ifdef DNS_WATCHDOG_SUPPORT
+/* sets the state of the DNS servers:
+ * 1: at least one server is up
+ * 0: all the servers are down
+ */
+void dns_set_server_state(int state)
+{
+       atomic_set(dns_servers_up, state);
+}
+#endif /* DNS_WATCHDOG_SUPPORT */
 
 /* rpc functions */
 void dns_cache_mem_info(rpc_t* rpc, void* ctx)
@@ -3026,5 +3098,16 @@ void dns_cache_debug_all(rpc_t* rpc, void* ctx)
        UNLOCK_DNS_HASH();
 }
 
+#ifdef DNS_WATCHDOG_SUPPORT
+/* sets the DNS server states */
+void dns_set_server_state_rpc(rpc_t* rpc, void* ctx)
+{
+       int     state;
+
+       if (rpc->scan(ctx, "d", &state) < 1)
+               return;
+       dns_set_server_state(state);
+}
+#endif /* DNS_WATCHDOG_SUPPORT */
 
 #endif
index f53dec0..1b97bfa 100644 (file)
 #error "DNS FAILOVER requires DNS CACHE support (define USE_DNS_CACHE)"
 #endif
 
+#if defined(DNS_WATCHDOG_SUPPORT) && !defined(USE_DNS_CACHE)
+#error "DNS WATCHDOG requires DNS CACHE support (define USE_DNS_CACHE)"
+#endif
+
 /* uncomment the define below for SRV weight based load balancing */
 #define DNS_SRV_LB
 
@@ -308,4 +312,13 @@ inline static int dns_sip_resolve2su(struct dns_srv_handle* h,
                init_su(su, &ip, port);
        return ret;
 }
+
+#ifdef DNS_WATCHDOG_SUPPORT
+/* sets the state of the DNS servers:
+ * 1: at least one server is up
+ * 0: all the servers are down
+ */
+void dns_set_server_state(int state);
+#endif /* DNS_WATCHDOG_SUPPORT */
+
 #endif
index d82cb22..ca69c8f 100644 (file)
--- a/version.h
+++ b/version.h
 #define USE_DNS_FAILOVER_STR ""
 #endif
 
+#ifdef DNS_WATCHDOG_SUPPORT
+#define DNS_WATCHDOG_SUPPORT_STR ", DNS_WATCHDOG_SUPPORT"
+#else
+#define DNS_WATCHDOG_SUPPORT_STR ""
+#endif
+
 #ifdef USE_NAPTR
 #define USE_NAPTR_STR ", USE_NAPTR"
 #else
        USE_FUTEX_STR \
        FAST_LOCK_STR NOSMP_STR USE_PTHREAD_MUTEX_STR USE_POSIX_SEM_STR \
        USE_SYSV_SEM_STR USE_COMP_STR USE_DNS_CACHE_STR USE_DNS_FAILOVER_STR \
-       USE_NAPTR_STR USE_DST_BLACKLIST_STR
+       DNS_WATCHDOG_SUPPORT_STR USE_NAPTR_STR USE_DST_BLACKLIST_STR
 
 
 #endif