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 404
 #         unsafe)
404 405
 # -DUSE_NAPTR
405 406
 #		 turns on naptr support (but must be also enabled from the config)
407
+# -DDNS_WATCHDOG_SUPPORT
408
+#		turns on DNS watchdog support which can be used to inform the
409
+#		core that the DNS servers are down. No DNS query is performed
410
+#		when the servers are unreachable, and even expired resource
411
+#		records are used from the cache. (requires external watchdog)
406 412
 
407 413
 # Sometimes is needes correct non-quoted $OS. HACK: gcc translates known OS to number ('linux'), so there is added underscore
408 414
 
... ...
@@ -423,6 +429,7 @@ DEFS+= $(extra_defs) \
423 429
 	 -DUSE_DNS_FAILOVER \
424 430
 	 -DUSE_DST_BLACKLIST \
425 431
 	 -DUSE_NAPTR \
432
+	 #-DDNS_WATCHDOG_SUPPORT \
426 433
 	 #-DLL_MALLOC \
427 434
 	 #-DSF_MALLOC \
428 435
 	 #-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 479
 	{"dns.mem_info",          dns_cache_mem_info,     dns_cache_mem_info_doc,     0	},
470 480
 	{"dns.debug",          dns_cache_debug,           dns_cache_debug_doc,        0	},
471 481
 	{"dns.debug_all",      dns_cache_debug_all,       dns_cache_debug_all_doc,        0	},
482
+#ifdef DNS_WATCHDOG_SUPPORT
483
+	{"dns.set_server_state",   dns_set_server_state_rpc, dns_set_server_state_doc, 0 },
484
+#endif
472 485
 #endif
473 486
 #ifdef USE_DST_BLACKLIST
474 487
 	{"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 114
 
113 115
 static struct timer_ln* dns_timer_h=0;
114 116
 
117
+#ifdef DNS_WATCHDOG_SUPPORT
118
+static atomic_t *dns_servers_up = NULL;
119
+#endif
120
+
115 121
 
116 122
 
117 123
 static const char* dns_str_errors[]={
... ...
@@ -192,6 +198,11 @@ inline static int dns_cache_free_mem(unsigned int target, int expired_only);
192 198
 
193 199
 static ticks_t dns_timer(ticks_t ticks, struct timer_ln* tl, void* data)
194 200
 {
201
+#ifdef DNS_WATCHDOG_SUPPORT
202
+	/* do not clean the hash table if the servers are down */
203
+	if (atomic_get(dns_servers_up) == 0)
204
+		return (ticks_t)(-1);
205
+#endif
195 206
 	if (*dns_cache_mem_used>12*(dns_cache_max_mem/16)){ /* ~ 75% used */
196 207
 		dns_cache_free_mem(dns_cache_max_mem/2, 1); 
197 208
 	}else{
... ...
@@ -210,6 +221,12 @@ void destroy_dns_cache()
210 221
 		timer_free(dns_timer_h);
211 222
 		dns_timer_h=0;
212 223
 	}
224
+#ifdef DNS_WATCHDOG_SUPPORT
225
+	if (dns_servers_up){
226
+		shm_free(dns_servers_up);
227
+		dns_servers_up=0;
228
+	}
229
+#endif
213 230
 	if (dns_hash_lock){
214 231
 		lock_destroy(dns_hash_lock);
215 232
 		lock_dealloc(dns_hash_lock);
... ...
@@ -277,6 +294,15 @@ int init_dns_cache()
277 294
 		ret=-1;
278 295
 		goto error;
279 296
 	}
297
+
298
+#ifdef DNS_WATCHDOG_SUPPORT
299
+	dns_servers_up=shm_malloc(sizeof(atomic_t));
300
+	if (dns_servers_up==0){
301
+		ret=E_OUT_OF_MEM;
302
+		goto error;
303
+	}
304
+	atomic_set(dns_servers_up, 1);
305
+#endif
280 306
 	
281 307
 	/* fix options */
282 308
 	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 439
 	ticks_t now;
414 440
 	int cname_chain;
415 441
 	str cname;
442
+#ifdef DNS_WATCHDOG_SUPPORT
443
+	int servers_up;
444
+
445
+	servers_up = atomic_get(dns_servers_up);
446
+#endif
416 447
 	
417 448
 	cname_chain=0;
418 449
 	ret=0;
... ...
@@ -425,8 +456,14 @@ again:
425 456
 												name->len, type, *h);
426 457
 #endif
427 458
 	clist_foreach_safe(&dns_hash[*h], e, tmp, next){
428
-		/* automatically remove expired elements */
429
-		if ((s_ticks_t)(now-e->expire)>=0){
459
+		if (
460
+#ifdef DNS_WATCHDOG_SUPPORT
461
+			/* remove expired elements only when the dns servers are up */
462
+			servers_up &&
463
+#endif
464
+			/* automatically remove expired elements */
465
+			((s_ticks_t)(now-e->expire)>=0)
466
+		) {
430 467
 				_dns_hash_remove(e);
431 468
 		}else if ((e->type==type) && (e->name_len==name->len) &&
432 469
 			(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 1513
 				goto end;/* we do not cache obvious stuff */
1477 1514
 		}
1478 1515
 	}
1516
+#ifdef DNS_WATCHDOG_SUPPORT
1517
+	if (atomic_get(dns_servers_up)==0)
1518
+		goto end; /* the servers are down, needless to perform the query */
1519
+#endif
1479 1520
 	if (name->len>=MAX_DNS_NAME){
1480 1521
 		LOG(L_ERR, "ERROR: dns_cache_do_request: name too long (%d chars)\n",
1481 1522
 					name->len);
... ...
@@ -1660,11 +1701,22 @@ inline static struct dns_rr* dns_entry_get_rr(	struct dns_hash_entry* e,
1660 1701
 	struct dns_rr* rr;
1661 1702
 	int n;
1662 1703
 	int flags;
1704
+#ifdef DNS_WATCHDOG_SUPPORT
1705
+	int servers_up;
1706
+
1707
+	servers_up = atomic_get(dns_servers_up);
1708
+#endif
1663 1709
 	
1664 1710
 	flags=0;
1665 1711
 	for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
1666 1712
 	for(;rr;rr=rr->next){
1667
-		if ((s_ticks_t)(now-e->expire)>=0) /* expired entry */
1713
+		if (
1714
+#ifdef DNS_WATCHDOG_SUPPORT
1715
+			/* check the expiration time only when the servers are up */
1716
+			servers_up &&
1717
+#endif
1718
+			((s_ticks_t)(now-rr->expire)>=0) /* expired rr */
1719
+		)
1668 1720
 			continue;
1669 1721
 		if (rr->err_flags){ /* bad rr */
1670 1722
 			continue;
... ...
@@ -1741,6 +1793,11 @@ inline static struct dns_rr* dns_srv_get_nxt_rr(struct dns_hash_entry* e,
1741 1793
 			unsigned r_sum;
1742 1794
 			struct dns_rr* rr;
1743 1795
 			}r_sums[MAX_SRV_GRP_IDX];
1796
+#ifdef DNS_WATCHDOG_SUPPORT
1797
+	int servers_up;
1798
+
1799
+	servers_up = atomic_get(dns_servers_up);
1800
+#endif
1744 1801
 	
1745 1802
 	rand_w=0;
1746 1803
 	for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
... ...
@@ -1755,7 +1812,12 @@ retry:
1755 1812
 	found=0;
1756 1813
 	for (idx=0;rr && (prio==((struct srv_rdata*)rr->rdata)->priority) &&
1757 1814
 						(idx < MAX_SRV_GRP_IDX); idx++, rr=rr->next){
1758
-		if ( ((s_ticks_t)(now-rr->expire)>=0) /* expired entry */ ||
1815
+		if ((
1816
+#ifdef DNS_WATCHDOG_SUPPORT
1817
+			/* check the expiration time only when the servers are up */
1818
+			servers_up &&
1819
+#endif
1820
+			((s_ticks_t)(now-rr->expire)>=0) /* expired entry */) ||
1759 1821
 				(rr->err_flags) /* bad rr */ ||
1760 1822
 				(srv_marked(tried, idx)) ) /* already tried */{
1761 1823
 			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 3001
 }
2940 3002
 
2941 3003
 
3004
+#ifdef DNS_WATCHDOG_SUPPORT
3005
+/* sets the state of the DNS servers:
3006
+ * 1: at least one server is up
3007
+ * 0: all the servers are down
3008
+ */
3009
+void dns_set_server_state(int state)
3010
+{
3011
+	atomic_set(dns_servers_up, state);
3012
+}
3013
+#endif /* DNS_WATCHDOG_SUPPORT */
2942 3014
 
2943 3015
 /* rpc functions */
2944 3016
 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 3098
 	UNLOCK_DNS_HASH();
3027 3099
 }
3028 3100
 
3101
+#ifdef DNS_WATCHDOG_SUPPORT
3102
+/* sets the DNS server states */
3103
+void dns_set_server_state_rpc(rpc_t* rpc, void* ctx)
3104
+{
3105
+	int	state;
3106
+
3107
+	if (rpc->scan(ctx, "d", &state) < 1)
3108
+		return;
3109
+	dns_set_server_state(state);
3110
+}
3111
+#endif /* DNS_WATCHDOG_SUPPORT */
3029 3112
 
3030 3113
 #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 312
 		init_su(su, &ip, port);
309 313
 	return ret;
310 314
 }
315
+
316
+#ifdef DNS_WATCHDOG_SUPPORT
317
+/* sets the state of the DNS servers:
318
+ * 1: at least one server is up
319
+ * 0: all the servers are down
320
+ */
321
+void dns_set_server_state(int state);
322
+#endif /* DNS_WATCHDOG_SUPPORT */
323
+
311 324
 #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 303
 	USE_FUTEX_STR \
298 304
 	FAST_LOCK_STR NOSMP_STR USE_PTHREAD_MUTEX_STR USE_POSIX_SEM_STR \
299 305
 	USE_SYSV_SEM_STR USE_COMP_STR USE_DNS_CACHE_STR USE_DNS_FAILOVER_STR \
300
-	USE_NAPTR_STR USE_DST_BLACKLIST_STR
306
+	DNS_WATCHDOG_SUPPORT_STR USE_NAPTR_STR USE_DST_BLACKLIST_STR
301 307
 
302 308
 
303 309
 #endif