don't keep stale NXDOMAIN cache entries

when serve-stale is enabled, NXDOMAIN cache entries are no longer
preserved after the normal negative cache TTL, in order to reduce
unnecessary cache memory consumption.

(cherry picked from commit f1485ca145)
This commit is contained in:
Evan Hunt
2022-06-03 16:22:01 -07:00
committed by Ondřej Surý
parent b6df5bfe2b
commit 2b78a2f9fa
2 changed files with 16 additions and 29 deletions

View File

@@ -173,10 +173,8 @@ status=$((status+ret))
n=$((n+1)) n=$((n+1))
echo_i "check stale nxdomain.example TXT ($n)" echo_i "check stale nxdomain.example TXT ($n)"
ret=0 ret=0
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret)) status=$((status+ret))
@@ -195,7 +193,6 @@ grep "1 TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #Others" ns1/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #Others" ns1/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #!TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #!TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #NXDOMAIN" ns1/named.stats.$n.cachedb > /dev/null || ret=1
status=$((status+ret)) status=$((status+ret))
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -409,10 +406,8 @@ status=$((status+ret))
n=$((n+1)) n=$((n+1))
echo_i "check stale nxdomain.example TXT (serve-stale on) ($n)" echo_i "check stale nxdomain.example TXT (serve-stale on) ($n)"
ret=0 ret=0
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret)) status=$((status+ret))
@@ -479,10 +474,8 @@ status=$((status+ret))
n=$((n+1)) n=$((n+1))
echo_i "check stale nxdomain.example TXT (serve-stale reset) ($n)" echo_i "check stale nxdomain.example TXT (serve-stale reset) ($n)"
ret=0 ret=0
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example\..*4.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret)) status=$((status+ret))
@@ -675,10 +668,8 @@ status=$((status+ret))
n=$((n+1)) n=$((n+1))
echo_i "check stale nxdomain.example TXT (low max-stale-ttl) ($n)" echo_i "check stale nxdomain.example TXT (low max-stale-ttl) ($n)"
ret=0 ret=0
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example\..*3.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret)) status=$((status+ret))
@@ -697,7 +688,6 @@ grep "1 TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #Others" ns1/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #Others" ns1/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #!TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #!TXT" ns1/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #NXDOMAIN" ns1/named.stats.$n.cachedb > /dev/null || ret=1
status=$((status+ret)) status=$((status+ret))
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -1118,7 +1108,6 @@ grep "1 TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #Others" ns3/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #Others" ns3/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #!TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #!TXT" ns3/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #NXDOMAIN" ns3/named.stats.$n.cachedb > /dev/null || ret=1
status=$((status+ret)) status=$((status+ret))
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -1193,10 +1182,8 @@ status=$((status+ret))
n=$((n+1)) n=$((n+1))
echo_i "check nxdomain.example TXT (max-stale-ttl default) ($n)" echo_i "check nxdomain.example TXT (max-stale-ttl default) ($n)"
ret=0 ret=0
grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1 grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
grep "EDE: 19 (Stale NXDOMAIN Answer): (resolver failure)" dig.out.test$n > /dev/null || ret=1
grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.test$n > /dev/null || ret=1
grep "example\..*30.*IN.*SOA" dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status+ret)) status=$((status+ret))
@@ -1369,7 +1356,6 @@ grep "1 TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #Others" ns4/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #Others" ns4/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #!TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 #!TXT" ns4/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 #NXDOMAIN" ns4/named.stats.$n.cachedb > /dev/null || ret=1
status=$((status+ret)) status=$((status+ret))
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -1497,7 +1483,6 @@ grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n > ns5/named.stats.$n.cache
grep "2 TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1 grep "2 TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 Others" ns5/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 Others" ns5/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 !TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1 grep "1 !TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1
grep "1 NXDOMAIN" ns5/named.stats.$n.cachedb > /dev/null || ret=1
status=$((status+ret)) status=$((status+ret))
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -1579,7 +1564,6 @@ grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n > ns5/named.stats.$n.cache
grep -F "1 Others" ns5/named.stats.$n.cachedb > /dev/null || ret=1 grep -F "1 Others" ns5/named.stats.$n.cachedb > /dev/null || ret=1
grep -F "2 TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1 grep -F "2 TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1
grep -F "1 !TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1 grep -F "1 !TXT" ns5/named.stats.$n.cachedb > /dev/null || ret=1
grep -F "1 NXDOMAIN" ns5/named.stats.$n.cachedb > /dev/null || ret=1
status=$((status+ret)) status=$((status+ret))
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi
@@ -1655,7 +1639,6 @@ grep -A 10 "++ Cache DB RRsets ++" ns5/named.stats.$n > ns5/named.stats.$n.cache
grep -F "#TXT" ns5/named.stats.$n.cachedb > /dev/null && ret=1 grep -F "#TXT" ns5/named.stats.$n.cachedb > /dev/null && ret=1
grep -F "#Others" ns5/named.stats.$n.cachedb > /dev/null && ret=1 grep -F "#Others" ns5/named.stats.$n.cachedb > /dev/null && ret=1
grep -F "#!TXT" ns5/named.stats.$n.cachedb > /dev/null && ret=1 grep -F "#!TXT" ns5/named.stats.$n.cachedb > /dev/null && ret=1
grep -F "#NXDOMAIN" ns5/named.stats.$n.cachedb > /dev/null && ret=1
status=$((status+ret)) status=$((status+ret))
if [ $ret != 0 ]; then echo_i "failed"; fi if [ $ret != 0 ]; then echo_i "failed"; fi

View File

@@ -297,6 +297,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t;
#define STATCOUNT(header) \ #define STATCOUNT(header) \
((atomic_load_acquire(&(header)->attributes) & \ ((atomic_load_acquire(&(header)->attributes) & \
RDATASET_ATTR_STATCOUNT) != 0) RDATASET_ATTR_STATCOUNT) != 0)
#define STALE_TTL(header, rbtdb) (NXDOMAIN(header) ? 0 : rbtdb->serve_stale_ttl)
#define RDATASET_ATTR_GET(header, attribute) \ #define RDATASET_ATTR_GET(header, attribute) \
(atomic_load_acquire(&(header)->attributes) & attribute) (atomic_load_acquire(&(header)->attributes) & attribute)
@@ -3003,7 +3004,8 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, rdatasetheader_t *header,
* Mark header stale or ancient if the RRset is no longer active. * Mark header stale or ancient if the RRset is no longer active.
*/ */
if (!ACTIVE(header, now)) { if (!ACTIVE(header, now)) {
dns_ttl_t stale_ttl = header->rdh_ttl + rbtdb->serve_stale_ttl; dns_ttl_t stale_ttl = header->rdh_ttl +
STALE_TTL(header, rbtdb);
/* /*
* If this data is in the stale window keep it and if * If this data is in the stale window keep it and if
* DNS_DBFIND_STALEOK is not set we tell the caller to * DNS_DBFIND_STALEOK is not set we tell the caller to
@@ -3043,7 +3045,8 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node, rdatasetheader_t *header,
} }
if (stale && !ancient) { if (stale && !ancient) {
dns_ttl_t stale_ttl = header->rdh_ttl + rbtdb->serve_stale_ttl; dns_ttl_t stale_ttl = header->rdh_ttl +
STALE_TTL(header, rbtdb);
if (stale_ttl > now) { if (stale_ttl > now) {
rdataset->ttl = stale_ttl - now; rdataset->ttl = stale_ttl - now;
} else { } else {
@@ -4468,7 +4471,7 @@ check_stale_header(dns_rbtnode_t *node, rdatasetheader_t *header,
rbtdb_search_t *search, rdatasetheader_t **header_prev) { rbtdb_search_t *search, rdatasetheader_t **header_prev) {
if (!ACTIVE(header, search->now)) { if (!ACTIVE(header, search->now)) {
dns_ttl_t stale = header->rdh_ttl + dns_ttl_t stale = header->rdh_ttl +
search->rbtdb->serve_stale_ttl; STALE_TTL(header, search->rbtdb);
/* /*
* If this data is in the stale window keep it and if * If this data is in the stale window keep it and if
* DNS_DBFIND_STALEOK is not set we tell the caller to * DNS_DBFIND_STALEOK is not set we tell the caller to
@@ -5606,7 +5609,7 @@ expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
isc_rwlocktype_write); isc_rwlocktype_write);
for (header = rbtnode->data; header != NULL; header = header->next) { for (header = rbtnode->data; header != NULL; header = header->next) {
if (header->rdh_ttl + rbtdb->serve_stale_ttl <= if (header->rdh_ttl + STALE_TTL(header, rbtdb) <=
now - RBTDB_VIRTUAL) now - RBTDB_VIRTUAL)
{ {
/* /*
@@ -5880,7 +5883,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
for (header = rbtnode->data; header != NULL; header = header_next) { for (header = rbtnode->data; header != NULL; header = header_next) {
header_next = header->next; header_next = header->next;
if (!ACTIVE(header, now)) { if (!ACTIVE(header, now)) {
if ((header->rdh_ttl + rbtdb->serve_stale_ttl < if ((header->rdh_ttl + STALE_TTL(header, rbtdb) <
now - RBTDB_VIRTUAL) && now - RBTDB_VIRTUAL) &&
(locktype == isc_rwlocktype_write || (locktype == isc_rwlocktype_write ||
NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS))
@@ -6959,8 +6962,9 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
} }
header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1); header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1);
if (header != NULL && header->rdh_ttl + rbtdb->serve_stale_ttl < if (header != NULL &&
now - RBTDB_VIRTUAL) header->rdh_ttl + STALE_TTL(header, rbtdb) <
now - RBTDB_VIRTUAL)
{ {
expire_header(rbtdb, header, tree_locked, expire_ttl); expire_header(rbtdb, header, tree_locked, expire_ttl);
} }