]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
selection: limit backing of the timeout
authorŠtěpán Balážik <stepan.balazik@nic.cz>
Tue, 8 Sep 2020 09:51:25 +0000 (11:51 +0200)
committerŠtěpán Balážik <stepan.balazik@nic.cz>
Thu, 15 Oct 2020 11:22:22 +0000 (13:22 +0200)
lib/selection.c
lib/selection_iter.c

index fe43223393a9674c465a5658a947c565d6b729c4..8fe967e4b90ba7c3764e51b6eadc869d26dca350 100644 (file)
@@ -38,6 +38,7 @@ void *prefix_key(const uint8_t *ip, size_t len) {
 
 #define DEFAULT_TIMEOUT 400
 #define MAX_TIMEOUT 10000
+#define MAX_BACKOFF 5
 
 const struct rtt_state default_rtt_state = {0, DEFAULT_TIMEOUT/4, 0};
 
@@ -108,14 +109,21 @@ bool no_rtt_info(struct rtt_state s) {
 
 #define MINIMAL_TIMEOUT_ADDITION 20
 
-// This is verbatim (minus the default timeout value and minimal variance) RFC2988, sec. 2
-int32_t calc_timeout(struct rtt_state state) {
-       int32_t timeout = state.srtt + MAX(4 * state.variance, MINIMAL_TIMEOUT_ADDITION);
-       timeout = timeout * (1 << state.consecutive_timeouts);
-       if (timeout > MAX_TIMEOUT) {
+unsigned back_off_timeout(uint32_t to, int pow) {
+       if (pow > MAX_BACKOFF) {
+               return to *= 1 << MAX_BACKOFF;
+       } else {
+               return to * (1 << pow);
+       }
+       if (to > MAX_TIMEOUT) {
                return MAX_TIMEOUT;
        }
-       return timeout;
+}
+
+// This is verbatim (minus the default timeout value and minimal variance) RFC2988, sec. 2
+unsigned calc_timeout(struct rtt_state state) {
+       int32_t timeout = state.srtt + MAX(4 * state.variance, MINIMAL_TIMEOUT_ADDITION);
+       return back_off_timeout(timeout, state.consecutive_timeouts);
 }
 
 // This is verbatim RFC2988, sec. 2
@@ -219,7 +227,7 @@ struct kr_transport *choose_transport(struct choice choices[],
        unsigned timeout = calc_timeout(choices[choice].address_state->rtt_state);
        if (no_rtt_info(choices[choice].address_state->rtt_state)) {
                // Exponential back-off when retrying after timeout and choosing an unknown server
-               timeout *= 1 << timeouts;
+               timeout = back_off_timeout(timeout, timeouts);
        }
 
        enum kr_transport_protocol protocol;
index f54c333ab8d5d39794f37e778000e9cb39ef6fdb..5b2cb3c94548294310e70dfd268f8011b6e429c6 100644 (file)
@@ -202,7 +202,7 @@ void iter_choose_transport(struct kr_query *qry, struct kr_transport **transport
                        const char *ns_str = kr_straddr(&(*transport)->address.ip);
                        if ((*transport)->protocol) {
                                VERBOSE_MSG(qry,
-                               "=> id: '%05u' choosing: '%s'@'%s' with timeout %d ms zone cut: '%s'\n",
+                               "=> id: '%05u' choosing: '%s'@'%s' with timeout %u ms zone cut: '%s'\n",
                                qry->id, ns_name, ns_str ? ns_str : "", (*transport)->timeout, zonecut_str);
                        } else {
                                VERBOSE_MSG(qry,