]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2058. [bug] Adjust how we calculate rtt estimates in the presence
authorMark Andrews <marka@isc.org>
Sat, 22 Jul 2006 01:20:53 +0000 (01:20 +0000)
committerMark Andrews <marka@isc.org>
Sat, 22 Jul 2006 01:20:53 +0000 (01:20 +0000)
                        of authoritative servers that drop EDNS and/or CD
                        requests.  Also fallback to EDNS/512 and plain DNS
                        faster for zones with less than 3 servers.  [RT #16187]

CHANGES
lib/dns/resolver.c

diff --git a/CHANGES b/CHANGES
index a17f458a4606df4a5c1c9743bf840cb299e6e68a..48e9e6f329dfe6f5cce51961119989453eafcd3a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+2058.  [bug]           Adjust how we calculate rtt estimates in the presence
+                       of authoritative servers that drop EDNS and/or CD
+                       requests.  Also fallback to EDNS/512 and plain DNS
+                       faster for zones with less than 3 servers.  [RT #16187]
+
 2057.  [bug]           Make setting "ra" dependent on both allow-query-cache
                        and allow-recursion. [RT #16290]
 
index 5091004c143c7a03a52487404b43ff6b42ab4f14..8d3730c6f51a3987c4a7a3f685a808850bb5bdac 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.284.18.47 2006/05/18 00:54:41 marka Exp $ */
+/* $Id: resolver.c,v 1.284.18.48 2006/07/22 01:20:53 marka Exp $ */
 
 /*! \file */
 
@@ -190,6 +190,8 @@ struct fetchctx {
        isc_sockaddrlist_t              forwarders;
        dns_fwdpolicy_t                 fwdpolicy;
        isc_sockaddrlist_t              bad;
+       isc_sockaddrlist_t              edns;
+       isc_sockaddrlist_t              edns512;
        ISC_LIST(dns_validator_t)       validators;
        dns_db_t *                      cache;
        dns_adb_t *                     adb;
@@ -570,8 +572,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
                         * slow.  We don't know.  Increase the RTT.
                         */
                        INSIST(no_response);
-                       rtt = query->addrinfo->srtt +
-                               (200000 * fctx->restarts);
+                       rtt = query->addrinfo->srtt + 200000;
                        if (rtt > 10000000)
                                rtt = 10000000;
                        /*
@@ -964,34 +965,37 @@ fctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
 static inline void
 fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
        unsigned int seconds;
+       unsigned int us;
 
        /*
-        * We retry every 2 seconds the first two times through the address
+        * We retry every .5 seconds the first two times through the address
         * list, and then we do exponential back-off.
         */
        if (fctx->restarts < 3)
-               seconds = 2;
+               us = 500000;
        else
-               seconds = (2 << (fctx->restarts - 1));
+               us = (500000 << (fctx->restarts - 2));
 
        /*
-        * Double the round-trip time and convert to seconds.
+        * Double the round-trip time.
         */
-       rtt /= 500000;
+       rtt *= 2;
 
        /*
         * Always wait for at least the doubled round-trip time.
         */
-       if (seconds < rtt)
-               seconds = rtt;
+       if (us < rtt)
+               us = rtt;
 
        /*
-        * But don't ever wait for more than 30 seconds.
+        * But don't ever wait for more than 10 seconds.
         */
-       if (seconds > 30)
-               seconds = 30;
+       if (us > 10000000)
+               us = 10000000;
 
-       isc_interval_set(&fctx->interval, seconds, 0);
+       seconds = us / 1000000;
+       us -= seconds * 1000000;
+       isc_interval_set(&fctx->interval, seconds, us * 1000);
 }
 
 static isc_result_t
@@ -1196,6 +1200,66 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
        return (result);
 }
 
+static isc_boolean_t
+triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
+       isc_sockaddr_t *sa;
+
+       for (sa = ISC_LIST_HEAD(fctx->edns);
+            sa != NULL;
+            sa = ISC_LIST_NEXT(sa, link)) {
+               if (isc_sockaddr_equal(sa, address))
+                       return (ISC_TRUE);
+       }
+
+       return (ISC_FALSE);
+}
+
+static void
+add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
+       isc_sockaddr_t *sa;
+
+       if (triededns(fctx, address))
+               return;
+
+       sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
+                        sizeof(*sa));
+       if (sa == NULL)
+               return;
+
+       *sa = *address;
+       ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);
+}
+
+static isc_boolean_t
+triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
+       isc_sockaddr_t *sa;
+
+       for (sa = ISC_LIST_HEAD(fctx->edns512);
+            sa != NULL;
+            sa = ISC_LIST_NEXT(sa, link)) {
+               if (isc_sockaddr_equal(sa, address))
+                       return (ISC_TRUE);
+       }
+
+       return (ISC_FALSE);
+}
+
+static void
+add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
+       isc_sockaddr_t *sa;
+
+       if (triededns512(fctx, address))
+               return;
+
+       sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,
+                        sizeof(*sa));
+       if (sa == NULL)
+               return;
+
+       *sa = *address;
+       ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);
+}
+
 static isc_result_t
 resquery_send(resquery_t *query) {
        fetchctx_t *fctx;
@@ -1346,12 +1410,14 @@ resquery_send(resquery_t *query) {
         * the remote server doesn't like it.
         */
 
-       if (fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2) &&
+       if ((triededns512(fctx, &query->addrinfo->sockaddr) ||
+            fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&
            (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
                query->options |= DNS_FETCHOPT_NOEDNS0;
                FCTXTRACE("too many timeouts, disabling EDNS0");
-       } else if (fctx->timeouts >= MAX_EDNS0_TIMEOUTS &&
-           (query->options & DNS_FETCHOPT_EDNS512) == 0) {
+       } else if ((triededns(fctx, &query->addrinfo->sockaddr) ||
+                   fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&
+                  (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
                query->options |= DNS_FETCHOPT_EDNS512;
                FCTXTRACE("too many timeouts, setting EDNS size to 512");
        }
@@ -1398,6 +1464,12 @@ resquery_send(resquery_t *query) {
                goto cleanup_message;
        }
 
+       if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)
+               add_triededns(fctx, &query->addrinfo->sockaddr);
+
+       if ((query->options & DNS_FETCHOPT_EDNS512) != 0)
+               add_triededns512(fctx, &query->addrinfo->sockaddr);
+
        /*
         * Clear CD if EDNS is not in use.
         */
@@ -2498,6 +2570,22 @@ fctx_destroy(fetchctx_t *fctx) {
                isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
        }
 
+       for (sa = ISC_LIST_HEAD(fctx->edns);
+            sa != NULL;
+            sa = next_sa) {
+               next_sa = ISC_LIST_NEXT(sa, link);
+               ISC_LIST_UNLINK(fctx->edns, sa, link);
+               isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+       }
+
+       for (sa = ISC_LIST_HEAD(fctx->edns512);
+            sa != NULL;
+            sa = next_sa) {
+               next_sa = ISC_LIST_NEXT(sa, link);
+               ISC_LIST_UNLINK(fctx->edns512, sa, link);
+               isc_mem_put(res->buckets[bucketnum].mctx, sa, sizeof(*sa));
+       }
+
        isc_timer_detach(&fctx->timer);
        dns_message_destroy(&fctx->rmessage);
        dns_message_destroy(&fctx->qmessage);
@@ -2850,6 +2938,8 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
        ISC_LIST_INIT(fctx->forwarders);
        fctx->fwdpolicy = dns_fwdpolicy_none;
        ISC_LIST_INIT(fctx->bad);
+       ISC_LIST_INIT(fctx->edns);
+       ISC_LIST_INIT(fctx->edns512);
        ISC_LIST_INIT(fctx->validators);
        fctx->find = NULL;
        fctx->altfind = NULL;