From f1485ca145a86a9df888e2364216e2887e969ec2 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Fri, 3 Jun 2022 16:22:01 -0700 Subject: [PATCH] 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. --- bin/tests/system/serve-stale/tests.sh | 27 +++++---------------------- lib/dns/rbtdb.c | 20 ++++++++++++-------- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/bin/tests/system/serve-stale/tests.sh b/bin/tests/system/serve-stale/tests.sh index ceea322a66..2e5ea6ab5b 100755 --- a/bin/tests/system/serve-stale/tests.sh +++ b/bin/tests/system/serve-stale/tests.sh @@ -173,10 +173,8 @@ status=$((status+ret)) n=$((n+1)) echo_i "check stale nxdomain.example ($n)" 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 "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 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 #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)) if [ $ret != 0 ]; then echo_i "failed"; fi @@ -409,10 +406,8 @@ status=$((status+ret)) n=$((n+1)) echo_i "check stale nxdomain.example (serve-stale on) ($n)" ret=0 -grep "status: NXDOMAIN" 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 "status: SERVFAIL" 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 status=$((status+ret)) @@ -479,10 +474,8 @@ status=$((status+ret)) n=$((n+1)) echo_i "check stale nxdomain.example (serve-stale reset) ($n)" ret=0 -grep "status: NXDOMAIN" 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 "status: SERVFAIL" 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 status=$((status+ret)) @@ -675,10 +668,8 @@ status=$((status+ret)) n=$((n+1)) echo_i "check stale nxdomain.example (low max-stale-ttl) ($n)" ret=0 -grep "status: NXDOMAIN" 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 "status: SERVFAIL" 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 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 #Others" 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)) 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 #Others" 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)) if [ $ret != 0 ]; then echo_i "failed"; fi @@ -1192,10 +1181,8 @@ status=$((status+ret)) n=$((n+1)) echo_i "check nxdomain.example (max-stale-ttl default) ($n)" ret=0 -grep "status: NXDOMAIN" 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 "status: SERVFAIL" 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 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 #Others" 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)) 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 "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 NXDOMAIN" ns5/named.stats.$n.cachedb > /dev/null || ret=1 status=$((status+ret)) 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 "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 NXDOMAIN" ns5/named.stats.$n.cachedb > /dev/null || ret=1 status=$((status+ret)) 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 "#Others" 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)) if [ $ret != 0 ]; then echo_i "failed"; fi diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 75c5d62a4e..2fd789cdca 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -297,6 +297,7 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t; #define STATCOUNT(header) \ ((atomic_load_acquire(&(header)->attributes) & \ RDATASET_ATTR_STATCOUNT) != 0) +#define STALE_TTL(header, rbtdb) (NXDOMAIN(header) ? 0 : rbtdb->serve_stale_ttl) #define RDATASET_ATTR_GET(header, 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. */ 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 * 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) { - 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) { rdataset->ttl = stale_ttl - now; } else { @@ -4435,7 +4438,7 @@ check_stale_header(dns_rbtnode_t *node, rdatasetheader_t *header, rbtdb_search_t *search, rdatasetheader_t **header_prev) { if (!ACTIVE(header, search->now)) { 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 * 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); 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) { /* * 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) { header_next = header->next; if (!ACTIVE(header, now)) { - if ((header->rdh_ttl + rbtdb->serve_stale_ttl < + if ((header->rdh_ttl + STALE_TTL(header, rbtdb) < now - RBTDB_VIRTUAL) && (locktype == isc_rwlocktype_write || 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); - if (header != NULL && header->rdh_ttl + rbtdb->serve_stale_ttl < - now - RBTDB_VIRTUAL) + if (header != NULL && + header->rdh_ttl + STALE_TTL(header, rbtdb) < + now - RBTDB_VIRTUAL) { expire_header(rbtdb, header, tree_locked, expire_ttl); } @@ -8688,7 +8692,7 @@ rdatasetiter_first(dns_rdatasetiter_t *iterator) { (now != 0 && (now - RBTDB_VIRTUAL) > header->rdh_ttl + - rbtdb->serve_stale_ttl)) + STALE_TTL(header, rbtdb))) { header = NULL; }