]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
selection: fix reporting of deduplicated packet
authorŠtěpán Balážik <stepan.balazik@nic.cz>
Tue, 1 Sep 2020 07:55:06 +0000 (09:55 +0200)
committerŠtěpán Balážik <stepan.balazik@nic.cz>
Thu, 15 Oct 2020 11:22:21 +0000 (13:22 +0200)
daemon/worker.c
lib/selection.c
lib/selection.h
lib/selection_forward.c
lib/selection_iter.c

index b01ef73d9ab4c790e159db197d0ba7db63f2c5c2..133592420031825c7c02f47483606dfb6ecfe8d2 100644 (file)
@@ -1115,7 +1115,12 @@ static void subreq_finalize(struct qr_task *task, const struct sockaddr *packet_
                        struct kr_query *qry = array_tail(follower->ctx->req.rplan.pending);
                        qry->id = leader_qry->id;
                        qry->secret = leader_qry->secret;
+
+                       // Note that this transport may not be present in `leader_qry`'s server selection
                        follower->transport = task->transport;
+                       if(follower->transport) {
+                               follower->transport->deduplicated = true;
+                       }
                        leader_qry->secret = 0; /* Next will be already decoded */
                }
                qr_task_step(follower, packet_source, pkt);
index 20eddcd19d0e2ea1cae9a6517786585fc274929c..1af07fe3234d13bcc5e54f1c679d56da991d26ce 100644 (file)
@@ -274,7 +274,7 @@ struct kr_transport *choose_transport(struct choice choices[],
 }
 
 void update_rtt(struct kr_query *qry, struct address_state *addr_state, const struct kr_transport *transport, unsigned rtt) {
-    if (!transport) {
+    if (!transport || !addr_state) {
         return;
     }
 
@@ -298,6 +298,11 @@ void update_rtt(struct kr_query *qry, struct address_state *addr_state, const st
 }
 
 void cache_timeout(const struct kr_transport *transport, struct address_state *addr_state, struct kr_cache *cache) {
+    if (transport->deduplicated) {
+        // Transport was chosen by a different query, that one will cache the result.
+        return;
+    }
+
     uint8_t *address = ip_to_bytes(&transport->address, transport->address_len);
     struct rtt_state old_state = addr_state->rtt_state;
     struct rtt_state cur_state = get_rtt_state(address, transport->address_len, cache);
@@ -311,7 +316,7 @@ void cache_timeout(const struct kr_transport *transport, struct address_state *a
 
 
 void error(struct kr_query *qry, struct address_state *addr_state, const struct kr_transport *transport, enum kr_selection_error sel_error) {
-    if (!transport) {
+    if (!transport || !addr_state) {
         return;
     }
 
@@ -321,7 +326,10 @@ void error(struct kr_query *qry, struct address_state *addr_state, const struct
 
     if (sel_error == KR_SELECTION_TIMEOUT) {
         qry->server_selection.timeouts++;
-        cache_timeout(transport, addr_state, &qry->request->ctx->cache);
+        if (!transport->deduplicated) {
+            // Make sure the query was chosen by this query
+            cache_timeout(transport, addr_state, &qry->request->ctx->cache);
+        }
     }
 
     addr_state->errors[sel_error]++;
index 55335902d820a033a4591f676e5b3e48e8fd0939..1251e302a6fbae56f446b5261ddd5f5ef1455907 100644 (file)
@@ -41,6 +41,8 @@ struct kr_transport {
     size_t address_len;
     enum kr_transport_protocol protocol;
     unsigned timeout;
+    bool deduplicated; // True iff transport was set in worker.c:subreq_finalize,
+                       // that means it may be different from the one originally chosen one.
 };
 
 struct kr_server_selection
index a4dda30239c7bce7e7b5a06a489fce380f8bbc9d..23385368fcb3603b6bea9ba119c88d1fb8da3c69 100644 (file)
@@ -77,12 +77,19 @@ void forward_success(struct kr_query *qry, const struct kr_transport *transport)
 }
 
 void forward_error(struct kr_query *qry, const struct kr_transport *transport, enum kr_selection_error sel_error) {
+    if (!qry->server_selection.initialized) {
+        return;
+    }
     struct forward_local_state *local_state = qry->server_selection.local_state;
        struct address_state *addr_state = &local_state->addr_states[local_state->last_choice_index];
     error(qry, addr_state, transport, sel_error);
 }
 
 void forward_update_rtt(struct kr_query *qry, const struct kr_transport *transport, unsigned rtt) {
+    if (!qry->server_selection.initialized) {
+        return;
+    }
+
     if (!transport) {
         return;
     }
index 6019cdf75038538f6b88662c3c122822595c7952..ea97f8f4248f79eef3bcb86e945de2b869982240 100644 (file)
@@ -25,18 +25,27 @@ struct iter_name_state {
     unsigned int generation;
 };
 
-void iter_local_state_init(struct knot_mm *mm, void **local_state) {
+void iter_local_state_alloc(struct knot_mm *mm, void **local_state) {
     *local_state = mm_alloc(mm, sizeof(struct iter_local_state));
     memset(*local_state, 0, sizeof(struct iter_local_state));
 }
 
 struct address_state *get_address_state(struct iter_local_state *local_state, const struct kr_transport *transport) {
+    if (!transport) {
+        return NULL;
+    }
+
        trie_t *addresses = local_state->addresses;
        uint8_t *address = ip_to_bytes(&transport->address, transport->address_len);
 
        trie_val_t *address_state = trie_get_try(addresses, (char *)address, transport->address_len);
 
        if (!address_state) {
+        if (transport->deduplicated) {
+            // Transport was chosen by a different query
+            return NULL;
+        }
+
                assert(0);
        }
        return (struct address_state *)*address_state;
@@ -196,12 +205,18 @@ void iter_success(struct kr_query *qry, const struct kr_transport *transport) {
 }
 
 void iter_error(struct kr_query *qry, const struct kr_transport *transport, enum kr_selection_error sel_error) {
+    if (!qry->server_selection.initialized) {
+        return;
+    }
        struct iter_local_state *local_state = qry->server_selection.local_state;
        struct address_state *addr_state = get_address_state(local_state, transport);
        error(qry, addr_state, transport, sel_error);
 }
 
 void iter_update_rtt(struct kr_query *qry, const struct kr_transport *transport, unsigned rtt) {
+    if (!qry->server_selection.initialized) {
+        return;
+    }
        struct iter_local_state *local_state = qry->server_selection.local_state;
        struct address_state *addr_state = get_address_state(local_state, transport);
     update_rtt(qry, addr_state, transport, rtt);