Browse code

DNS watchdog support implementation: a SER module or an external application can inform the core that the DNS servers 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)

Miklos Tirpak authored on 26/07/2007 11:18:34
Showing 5 changed files
... ...
@@ -60,6 +60,7 @@
60 60
 #  2007-05-26  changed darwin module link flags (instead of -bundle_loader ser
61 61
 #               -flat_namespace -undefined suppress) (andrei)
62 62
 #  2007-07-07  added HAVE_SCHED_SETSCHEDULER for linux (andrei)
63
+#  2007-07-18  added DNS_WATCHDOG_SUPPORT (Miklos)
63 64
 
64 65
 # check if already included/exported
65 66
 
... ...
@@ -403,6 +404,11 @@ endif
403 403
 #         unsafe)
404 404
 # -DUSE_NAPTR
405 405
 #		 turns on naptr support (but must be also enabled from the config)
406
+# -DDNS_WATCHDOG_SUPPORT
407
+#		turns on DNS watchdog support which can be used to inform the
408
+#		core that the DNS servers are down. No DNS query is performed
409
+#		when the servers are unreachable, and even expired resource
410
+#		records are used from the cache. (requires external watchdog)
406 411
 
407 412
 # Sometimes is needes correct non-quoted $OS. HACK: gcc translates known OS to number ('linux'), so there is added underscore
408 413
 
... ...
@@ -423,6 +429,7 @@ DEFS+= $(extra_defs) \
423 423
 	 -DUSE_DNS_FAILOVER \
424 424
 	 -DUSE_DST_BLACKLIST \
425 425
 	 -DUSE_NAPTR \
426
+	 #-DDNS_WATCHDOG_SUPPORT \
426 427
 	 #-DLL_MALLOC \
427 428
 	 #-DSF_MALLOC \
428 429
 	 #-DDL_MALLOC \
... ...
@@ -57,7 +57,17 @@ static const char* dns_cache_debug_all_doc[] = {
57 57
 	"complete dns debug  dump",    /* Documentation string */
58 58
 	0                              /* Method signature(s) */
59 59
 };
60
-#endif
60
+
61
+#ifdef DNS_WATCHDOG_SUPPORT
62
+void dns_set_server_state_rpc(rpc_t* rpc, void* ctx);
63
+
64
+static const char* dns_set_server_state_doc[] = {
65
+	"sets the state of the DNS servers " \
66
+	"(0: all the servers are down, 1: at least one server is up)",    /* Documentation string */
67
+	0                              /* Method signature(s) */
68
+};
69
+#endif /* DNS_WATCHDOG_SUPPORT */
70
+#endif /* USE_DNS_CACHE */
61 71
 #ifdef USE_DST_BLACKLIST
62 72
 void dst_blst_debug(rpc_t* rpc, void* ctx);
63 73
 void dst_blst_mem_info(rpc_t* rpc, void* ctx);
... ...
@@ -469,6 +479,9 @@ rpc_export_t core_rpc_methods[] = {
469 469
 	{"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,     0	},
470 470
 	{"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,        0	},
471 471
 	{"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,        0	},
472
+#ifdef DNS_WATCHDOG_SUPPORT
473
+	{"dns.set_server_state",   dns_set_server_state_rpc, dns_set_server_state_doc, 0 },
474
+#endif
472 475
 #endif
473 476
 #ifdef USE_DST_BLACKLIST
474 477
 	{"dst_blacklist.mem_info",  dst_blst_mem_info,     dst_blst_mem_info_doc,     0	},
... ...
@@ -33,6 +33,8 @@
33 33
  *  2007-06-14  dns iterate through A & AAAA records fix (andrei)
34 34
  *  2007-06-15  srv rr weight based load balancing support (andrei)
35 35
  *  2007-06-16  naptr support (andrei)
36
+ *  2008-07-18  DNS watchdog support -- can be used to inform the core
37
+ *              that the DNS servers are down (Miklos)
36 38
  */
37 39
 
38 40
 #ifdef USE_DNS_CACHE
... ...
@@ -112,6 +114,10 @@ static struct dns_hash_head* dns_hash=0;
112 112
 
113 113
 static struct timer_ln* dns_timer_h=0;
114 114
 
115
+#ifdef DNS_WATCHDOG_SUPPORT
116
+static atomic_t *dns_servers_up = NULL;
117
+#endif
118
+
115 119
 
116 120
 
117 121
 static const char* dns_str_errors[]={
... ...
@@ -192,6 +198,11 @@ inline static int dns_cache_free_mem(unsigned int target, int expired_only);
192 192
 
193 193
 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
194 194
 {
195
+#ifdef DNS_WATCHDOG_SUPPORT
196
+	/* do not clean the hash table if the servers are down */
197
+	if (atomic_get(dns_servers_up) == 0)
198
+		return (ticks_t)(-1);
199
+#endif
195 200
 	if (*dns_cache_mem_used>12*(dns_cache_max_mem/16)){ /* ~ 75% used */
196 201
 		dns_cache_free_mem(dns_cache_max_mem/2, 1); 
197 202
 	}else{
... ...
@@ -210,6 +221,12 @@ void destroy_dns_cache()
210 210
 		timer_free(dns_timer_h);
211 211
 		dns_timer_h=0;
212 212
 	}
213
+#ifdef DNS_WATCHDOG_SUPPORT
214
+	if (dns_servers_up){
215
+		shm_free(dns_servers_up);
216
+		dns_servers_up=0;
217
+	}
218
+#endif
213 219
 	if (dns_hash_lock){
214 220
 		lock_destroy(dns_hash_lock);
215 221
 		lock_dealloc(dns_hash_lock);
... ...
@@ -277,6 +294,15 @@ int init_dns_cache()
277 277
 		ret=-1;
278 278
 		goto error;
279 279
 	}
280
+
281
+#ifdef DNS_WATCHDOG_SUPPORT
282
+	dns_servers_up=shm_malloc(sizeof(atomic_t));
283
+	if (dns_servers_up==0){
284
+		ret=E_OUT_OF_MEM;
285
+		goto error;
286
+	}
287
+	atomic_set(dns_servers_up, 1);
288
+#endif
280 289
 	
281 290
 	/* fix options */
282 291
 	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,
413 413
 	ticks_t now;
414 414
 	int cname_chain;
415 415
 	str cname;
416
+#ifdef DNS_WATCHDOG_SUPPORT
417
+	int servers_up;
418
+
419
+	servers_up = atomic_get(dns_servers_up);
420
+#endif
416 421
 	
417 422
 	cname_chain=0;
418 423
 	ret=0;
... ...
@@ -425,8 +456,14 @@ again:
425 425
 												name->len, type, *h);
426 426
 #endif
427 427
 	clist_foreach_safe(&dns_hash[*h], e, tmp, next){
428
-		/* automatically remove expired elements */
429
-		if ((s_ticks_t)(now-e->expire)>=0){
428
+		if (
429
+#ifdef DNS_WATCHDOG_SUPPORT
430
+			/* remove expired elements only when the dns servers are up */
431
+			servers_up &&
432
+#endif
433
+			/* automatically remove expired elements */
434
+			((s_ticks_t)(now-e->expire)>=0)
435
+		) {
430 436
 				_dns_hash_remove(e);
431 437
 		}else if ((e->type==type) && (e->name_len==name->len) &&
432 438
 			(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)
1476 1476
 				goto end;/* we do not cache obvious stuff */
1477 1477
 		}
1478 1478
 	}
1479
+#ifdef DNS_WATCHDOG_SUPPORT
1480
+	if (atomic_get(dns_servers_up)==0)
1481
+		goto end; /* the servers are down, needless to perform the query */
1482
+#endif
1479 1483
 	if (name->len>=MAX_DNS_NAME){
1480 1484
 		LOG(L_ERR, "ERROR: dns_cache_do_request: name too long (%d chars)\n",
1481 1485
 					name->len);
... ...
@@ -1660,11 +1701,22 @@ inline static struct dns_rr* dns_entry_get_rr(	struct dns_hash_entry* e,
1660 1660
 	struct dns_rr* rr;
1661 1661
 	int n;
1662 1662
 	int flags;
1663
+#ifdef DNS_WATCHDOG_SUPPORT
1664
+	int servers_up;
1665
+
1666
+	servers_up = atomic_get(dns_servers_up);
1667
+#endif
1663 1668
 	
1664 1669
 	flags=0;
1665 1670
 	for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
1666 1671
 	for(;rr;rr=rr->next){
1667
-		if ((s_ticks_t)(now-e->expire)>=0) /* expired entry */
1672
+		if (
1673
+#ifdef DNS_WATCHDOG_SUPPORT
1674
+			/* check the expiration time only when the servers are up */
1675
+			servers_up &&
1676
+#endif
1677
+			((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
1678
+		)
1668 1679
 			continue;
1669 1680
 		if (rr->err_flags){ /* bad rr */
1670 1681
 			continue;
... ...
@@ -1741,6 +1793,11 @@ inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
1741 1741
 			unsigned r_sum;
1742 1742
 			struct dns_rr* rr;
1743 1743
 			}r_sums[MAX_SRV_GRP_IDX];
1744
+#ifdef DNS_WATCHDOG_SUPPORT
1745
+	int servers_up;
1746
+
1747
+	servers_up = atomic_get(dns_servers_up);
1748
+#endif
1744 1749
 	
1745 1750
 	rand_w=0;
1746 1751
 	for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
... ...
@@ -1755,7 +1812,12 @@ retry:
1755 1755
 	found=0;
1756 1756
 	for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
1757 1757
 						(idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
1758
-		if ( ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */ ||
1758
+		if ((
1759
+#ifdef DNS_WATCHDOG_SUPPORT
1760
+			/* check the expiration time only when the servers are up */
1761
+			servers_up &&
1762
+#endif
1763
+			((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
1759 1764
 				(rr->err_flags) /* bad rr */ ||
1760 1765
 				(srv_marked(tried, idx)) ) /* already tried */{
1761 1766
 			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,
2939 2939
 }
2940 2940
 
2941 2941
 
2942
+#ifdef DNS_WATCHDOG_SUPPORT
2943
+/* sets the state of the DNS servers:
2944
+ * 1: at least one server is up
2945
+ * 0: all the servers are down
2946
+ */
2947
+void dns_set_server_state(int state)
2948
+{
2949
+	atomic_set(dns_servers_up, state);
2950
+}
2951
+#endif /* DNS_WATCHDOG_SUPPORT */
2942 2952
 
2943 2953
 /* rpc functions */
2944 2954
 void dns_cache_mem_info(rpc_t* rpc, void* ctx)
... ...
@@ -3026,5 +3098,16 @@ void dns_cache_debug_all(rpc_t* rpc, void* ctx)
3026 3026
 	UNLOCK_DNS_HASH();
3027 3027
 }
3028 3028
 
3029
+#ifdef DNS_WATCHDOG_SUPPORT
3030
+/* sets the DNS server states */
3031
+void dns_set_server_state_rpc(rpc_t* rpc, void* ctx)
3032
+{
3033
+	int	state;
3034
+
3035
+	if (rpc->scan(ctx, "d", &state) < 1)
3036
+		return;
3037
+	dns_set_server_state(state);
3038
+}
3039
+#endif /* DNS_WATCHDOG_SUPPORT */
3029 3040
 
3030 3041
 #endif
... ...
@@ -48,6 +48,10 @@
48 48
 #error "DNS FAILOVER requires DNS CACHE support (define USE_DNS_CACHE)"
49 49
 #endif
50 50
 
51
+#if defined(DNS_WATCHDOG_SUPPORT) && !defined(USE_DNS_CACHE)
52
+#error "DNS WATCHDOG requires DNS CACHE support (define USE_DNS_CACHE)"
53
+#endif
54
+
51 55
 /* uncomment the define below for SRV weight based load balancing */
52 56
 #define DNS_SRV_LB
53 57
 
... ...
@@ -308,4 +312,13 @@ inline static int dns_sip_resolve2su(struct dns_srv_handle* h,
308 308
 		init_su(su, &ip, port);
309 309
 	return ret;
310 310
 }
311
+
312
+#ifdef DNS_WATCHDOG_SUPPORT
313
+/* sets the state of the DNS servers:
314
+ * 1: at least one server is up
315
+ * 0: all the servers are down
316
+ */
317
+void dns_set_server_state(int state);
318
+#endif /* DNS_WATCHDOG_SUPPORT */
319
+
311 320
 #endif
... ...
@@ -260,6 +260,12 @@
260 260
 #define USE_DNS_FAILOVER_STR ""
261 261
 #endif
262 262
 
263
+#ifdef DNS_WATCHDOG_SUPPORT
264
+#define DNS_WATCHDOG_SUPPORT_STR ", DNS_WATCHDOG_SUPPORT"
265
+#else
266
+#define DNS_WATCHDOG_SUPPORT_STR ""
267
+#endif
268
+
263 269
 #ifdef USE_NAPTR
264 270
 #define USE_NAPTR_STR ", USE_NAPTR"
265 271
 #else
... ...
@@ -297,7 +303,7 @@
297 297
 	USE_FUTEX_STR \
298 298
 	FAST_LOCK_STR NOSMP_STR USE_PTHREAD_MUTEX_STR USE_POSIX_SEM_STR \
299 299
 	USE_SYSV_SEM_STR USE_COMP_STR USE_DNS_CACHE_STR USE_DNS_FAILOVER_STR \
300
-	USE_NAPTR_STR USE_DST_BLACKLIST_STR
300
+	DNS_WATCHDOG_SUPPORT_STR USE_NAPTR_STR USE_DST_BLACKLIST_STR
301 301
 
302 302
 
303 303
 #endif