diff options
author | Daniel Mack <github@zonque.org> | 2015-08-03 16:32:40 +0200 |
---|---|---|
committer | Daniel Mack <github@zonque.org> | 2015-08-03 16:32:40 +0200 |
commit | 4d2bee0620c04f935f7de0cc10d8d5e5d3e54b6a (patch) | |
tree | 25bad1f1b28175fac701af9bc7d2d1a1e14f0849 /src/resolve/resolved-dns-transaction.c | |
parent | b04d9f28718fe551ff8668e9c2eac2b2283e27ca (diff) | |
parent | 3b31df8301fd7dfb78bf9eaf9227d40c9bf12182 (diff) |
Merge pull request #841 from teg/resolved-exponential-resend
resolved: exponential backoff of packet resend
Diffstat (limited to 'src/resolve/resolved-dns-transaction.c')
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index 8a93b265c6..487b2c5162 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -319,11 +319,14 @@ static void dns_transaction_next_dns_server(DnsTransaction *t) { } void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { + usec_t ts; int r; assert(t); assert(p); assert(t->state == DNS_TRANSACTION_PENDING); + assert(t->scope); + assert(t->scope->manager); /* Note that this call might invalidate the query. Callers * should hence not attempt to access the query or transaction @@ -369,6 +372,26 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { } } + r = sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts); + if (r < 0) + ts = now(clock_boottime_or_monotonic()); + + switch (t->scope->protocol) { + case DNS_PROTOCOL_DNS: + assert(t->server); + + dns_server_packet_received(t->server, ts - t->start_usec); + + break; + case DNS_PROTOCOL_LLMNR: + case DNS_PROTOCOL_MDNS: + dns_scope_packet_received(t->scope, ts - t->start_usec); + + break; + default: + assert_not_reached("Invalid DNS protocol."); + } + if (DNS_PACKET_TC(p)) { /* Response was truncated, let's try again with good old TCP */ r = dns_transaction_open_tcp(t); @@ -434,9 +457,9 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use return r; if (dns_packet_validate_reply(p) > 0 && - DNS_PACKET_ID(p) == t->id) { + DNS_PACKET_ID(p) == t->id) dns_transaction_process_reply(t, p); - } else + else log_debug("Invalid DNS packet."); return 0; @@ -481,6 +504,12 @@ static int on_transaction_timeout(sd_event_source *s, usec_t usec, void *userdat /* Timeout reached? Try again, with a new server */ dns_transaction_next_dns_server(t); + /* ... and possibly increased timeout */ + if (t->server) + dns_server_packet_lost(t->server, usec - t->start_usec); + else + dns_scope_packet_lost(t->scope, usec - t->start_usec); + r = dns_transaction_go(t); if (r < 0) dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES); @@ -528,8 +557,26 @@ static int dns_transaction_make_packet(DnsTransaction *t) { return 0; } +static usec_t transaction_get_resend_timeout(DnsTransaction *t) { + assert(t); + assert(t->scope); + + switch (t->scope->protocol) { + case DNS_PROTOCOL_DNS: + assert(t->server); + + return t->server->resend_timeout; + case DNS_PROTOCOL_LLMNR: + case DNS_PROTOCOL_MDNS: + return t->scope->resend_timeout; + default: + assert_not_reached("Invalid DNS protocol."); + } +} + int dns_transaction_go(DnsTransaction *t) { bool had_stream; + usec_t ts; int r; assert(t); @@ -555,7 +602,12 @@ int dns_transaction_go(DnsTransaction *t) { return 0; } + r = sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts); + if (r < 0) + ts = now(clock_boottime_or_monotonic()); + t->n_attempts++; + t->start_usec = ts; t->received = dns_packet_unref(t->received); t->cached = dns_answer_unref(t->cached); t->cached_rcode = 0; @@ -600,7 +652,7 @@ int dns_transaction_go(DnsTransaction *t) { t->scope->manager->event, &t->timeout_event_source, clock_boottime_or_monotonic(), - now(clock_boottime_or_monotonic()) + jitter, + ts + jitter, LLMNR_JITTER_INTERVAL_USEC, on_transaction_timeout, t); if (r < 0) @@ -660,7 +712,7 @@ int dns_transaction_go(DnsTransaction *t) { t->scope->manager->event, &t->timeout_event_source, clock_boottime_or_monotonic(), - now(clock_boottime_or_monotonic()) + TRANSACTION_TIMEOUT_USEC(t->scope->protocol), 0, + ts + transaction_get_resend_timeout(t), 0, on_transaction_timeout, t); if (r < 0) return r; |