From d56d2a32b861e81c2aaaabd309c4c58b629ede32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 17 Jun 2024 11:40:40 +0200 Subject: [PATCH 1/3] Expand the list of the priority types Add HTTPS, SVCB, SRV, PTR, NAPTR, DNSKEY and TXT records to the list of the priority types that are put at the beginning of the slabheader list for faster access and to avoid eviction when there are more types than the max-types-per-name limit. (cherry picked from commit b27c6bcce894786a8e082eafd59eccbf6f2731cb) --- lib/dns/rbtdb.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index b35e101b01..09324536b3 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -990,6 +990,8 @@ prio_type(rbtdb_rdatatype_t type) { case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_soa): case dns_rdatatype_a: case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_a): + case dns_rdatatype_mx: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_mx): case dns_rdatatype_aaaa: case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_aaaa): case dns_rdatatype_nsec: @@ -1002,6 +1004,22 @@ prio_type(rbtdb_rdatatype_t type) { case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ds): case dns_rdatatype_cname: case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_cname): + case dns_rdatatype_dname: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dname): + case dns_rdatatype_svcb: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_svcb): + case dns_rdatatype_https: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_https): + case dns_rdatatype_dnskey: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dnskey): + case dns_rdatatype_srv: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_srv): + case dns_rdatatype_txt: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_txt): + case dns_rdatatype_ptr: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ptr): + case dns_rdatatype_naptr: + case RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_naptr): return (true); } return (false); From c5ebda6deb0997dc520b26fa0639891459de5cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 17 Jun 2024 17:54:09 +0200 Subject: [PATCH 2/3] Make the resolver qtype ANY test order agnostic Instead of relying on a specific order of the RR types in the databases pick the first RR type as returned from the cache. (cherry picked from commit 58f660cf2b800963fa649bc9823a626009db3a7e) --- bin/tests/system/resolver/tests.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh index fc05635e31..2e089fa371 100755 --- a/bin/tests/system/resolver/tests.sh +++ b/bin/tests/system/resolver/tests.sh @@ -596,18 +596,18 @@ n=$((n + 1)) echo_i "check prefetch qtype * (${n})" ret=0 dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.1.${n} || ret=1 -ttl1=$(awk '/"A" "short" "ttl"/ { print $2 - 3 }' dig.out.1.${n}) +ttl1=$(awk '/^fetchall.tld/ { print $2 - 3; exit }' dig.out.1.${n}) # sleep so we are in prefetch range sleep "${ttl1:-0}" # trigger prefetch dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.2.${n} || ret=1 -ttl2=$(awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}) +ttl2=$(awk '/^fetchall.tld/ { print $2; exit }' dig.out.2.${n}) sleep 1 # check that prefetch occurred; -# note that only one record is prefetched, which is the AAAA record in this case, +# note that only the first record is prefetched, # because of the order of the records in the cache dig_with_opts @10.53.0.5 fetchall.tld any >dig.out.3.${n} || ret=1 -ttl3=$(awk '/::1/ { print $2 }' dig.out.3.${n}) +ttl3=$(awk '/^fetchall.tld/ { print $2; exit }' dig.out.3.${n}) test "${ttl3:-0}" -gt "${ttl2:-1}" || ret=1 if [ $ret != 0 ]; then echo_i "failed"; fi status=$((status + ret)) From 26c9da5f2857b72077c17e06ac79f068c63782cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Mon, 17 Jun 2024 11:40:40 +0200 Subject: [PATCH 3/3] Be smarter about refusing to add many RR types to the database Instead of outright refusing to add new RR types to the cache, be a bit smarter: 1. If the new header type is in our priority list, we always add either positive or negative entry at the beginning of the list. 2. If the new header type is negative entry, and we are over the limit, we mark it as ancient immediately, so it gets evicted from the cache as soon as possible. 3. Otherwise add the new header after the priority headers (or at the head of the list). 4. If we are over the limit, evict the last entry on the normal header list. (cherry picked from commit 57cd34441a1b4ecc9874a4a106c2c95b8d7a3120) --- lib/dns/rbtdb.c | 68 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 11 deletions(-) diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 09324536b3..9670671d1e 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -6262,6 +6262,26 @@ update_recordsandxfrsize(bool add, rbtdb_version_t *rbtversion, #define DNS_RBTDB_MAX_RTYPES 100 #endif /* DNS_RBTDB_MAX_RTYPES */ +static bool +overmaxtype(dns_rbtdb_t *rbtdb, uint32_t ntypes) { + UNUSED(rbtdb); + + if (DNS_RBTDB_MAX_RTYPES == 0) { + return (false); + } + + return (ntypes >= DNS_RBTDB_MAX_RTYPES); +} + +static bool +prio_header(rdatasetheader_t *header) { + if (NEGATIVE(header) && prio_type(RBTDB_RDATATYPE_EXT(header->type))) { + return (true); + } + + return (prio_type(header->type)); +} + /* * write lock on rbtnode must be held. */ @@ -6273,7 +6293,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename, rbtdb_changed_t *changed = NULL; rdatasetheader_t *topheader = NULL, *topheader_prev = NULL; rdatasetheader_t *header = NULL, *sigheader = NULL; - rdatasetheader_t *prioheader = NULL; + rdatasetheader_t *prioheader = NULL, *expireheader = NULL; unsigned char *merged = NULL; isc_result_t result; bool header_nx; @@ -6283,7 +6303,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename, rbtdb_rdatatype_t negtype, sigtype; dns_trust_t trust; int idx; - uint32_t ntypes; + uint32_t ntypes = 0; /* * Add an rdatasetheader_t to a node. @@ -6348,7 +6368,6 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename, set_ttl(rbtdb, topheader, 0); mark_header_ancient(rbtdb, topheader); } - ntypes = 0; goto find_header; } /* @@ -6360,6 +6379,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename, { if (topheader->type == sigtype) { sigheader = topheader; + break; } } negtype = RBTDB_RDATATYPE_VALUE(covers, 0); @@ -6372,11 +6392,9 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename, * check for an extant non-ancient NODATA ncache * entry which covers the same type as the RRSIG. */ - ntypes = 0; for (topheader = rbtnode->data; topheader != NULL; topheader = topheader->next) { - ntypes++; if ((topheader->type == RBTDB_RDATATYPE_NCACHEANY) || (newheader->type == sigtype && @@ -6421,12 +6439,16 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, const dns_name_t *nodename, } } - ntypes = 0; for (topheader = rbtnode->data; topheader != NULL; topheader = topheader->next) { - ntypes++; - if (prio_type(topheader->type)) { + if (IS_CACHE(rbtdb) && ACTIVE(topheader, now)) { + ++ntypes; + expireheader = topheader; + } else if (!IS_CACHE(rbtdb)) { + ++ntypes; + } + if (prio_header(topheader)) { prioheader = topheader; } if (topheader->type == newheader->type || @@ -6783,8 +6805,7 @@ find_header: /* * No rdatasets of the given type exist at the node. */ - - if (ntypes > DNS_RBTDB_MAX_RTYPES) { + if (!IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) { free_rdataset(rbtdb, rbtdb->common.mctx, newheader); return (ISC_R_QUOTA); @@ -6792,7 +6813,7 @@ find_header: newheader->down = NULL; - if (prio_type(newheader->type)) { + if (prio_header(newheader)) { /* This is a priority type, prepend it */ newheader->next = rbtnode->data; rbtnode->data = newheader; @@ -6805,6 +6826,31 @@ find_header: newheader->next = rbtnode->data; rbtnode->data = newheader; } + + if (IS_CACHE(rbtdb) && overmaxtype(rbtdb, ntypes)) { + if (expireheader == NULL) { + expireheader = newheader; + } + if (NEGATIVE(newheader) && + !prio_header(newheader)) + { + /* + * Add the new non-priority negative + * header to the database only + * temporarily. + */ + expireheader = newheader; + } + + set_ttl(rbtdb, expireheader, 0); + mark_header_ancient(rbtdb, expireheader); + /* + * FIXME: In theory, we should mark the RRSIG + * and the header at the same time, but there is + * no direct link between those two header, so + * we would have to check the whole list again. + */ + } } }