2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 22:15:20 +00:00

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.
This commit is contained in:
Evan Hunt
2022-06-03 16:22:01 -07:00
parent ae09f1d89f
commit f1485ca145
2 changed files with 17 additions and 30 deletions

View File

@@ -173,10 +173,8 @@ status=$((status+ret))
n=$((n+1)) n=$((n+1))
echo_i "check stale nxdomain.example ($n)" echo_i "check stale nxdomain.example ($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 (serve-stale on) ($n)" echo_i "check stale nxdomain.example (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 (serve-stale reset) ($n)" echo_i "check stale nxdomain.example (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 (low max-stale-ttl) ($n)" echo_i "check stale nxdomain.example (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
@@ -1192,10 +1181,8 @@ status=$((status+ret))
n=$((n+1)) n=$((n+1))
echo_i "check nxdomain.example (max-stale-ttl default) ($n)" echo_i "check nxdomain.example (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))
@@ -1368,7 +1355,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
@@ -1496,7 +1482,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
@@ -1578,7 +1563,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
@@ -1654,7 +1638,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)
@@ -2985,7 +2986,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
@@ -3025,7 +3027,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 {
@@ -4435,7 +4438,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
@@ -5556,7 +5559,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) {
/* /*
* We don't check if refcurrent(rbtnode) == 0 and try * We don't check if refcurrent(rbtnode) == 0 and try
@@ -5828,7 +5831,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))
@@ -6893,8 +6896,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);
} }
@@ -8688,7 +8692,7 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator) {
(now != 0 && (now != 0 &&
(now - RBTDB_VIRTUAL) > (now - RBTDB_VIRTUAL) >
header->rdh_ttl + header->rdh_ttl +
rbtdb->serve_stale_ttl)) STALE_TTL(header, rbtdb)))
{ {
header = NULL; header = NULL;
} }