mirror of
https://github.com/systemd/systemd.git
synced 2024-10-31 16:21:26 +03:00
resolved: don't redundantly switch DNS servers because of transaction failures
When a transaction fails and we decide to switch DNS servers, don#t do so unconditionally. Check if the current DNS server is still the same as when the transaction was initiated. And if not, do not do anything. That should reduce the number of redundant DNS server switches if many parallel transactions fail simultaneously (which is pretty likely if DNSSEC is on). Fixes: #17040
This commit is contained in:
parent
c78735eb79
commit
5e8bc852d5
@ -153,16 +153,19 @@ unsigned dns_scope_get_n_dns_servers(DnsScope *s) {
|
||||
return n;
|
||||
}
|
||||
|
||||
void dns_scope_next_dns_server(DnsScope *s) {
|
||||
void dns_scope_next_dns_server(DnsScope *s, DnsServer *if_current) {
|
||||
assert(s);
|
||||
|
||||
if (s->protocol != DNS_PROTOCOL_DNS)
|
||||
return;
|
||||
|
||||
/* Changes to the next DNS server in the list. If 'if_current' is passed will do so only if the
|
||||
* current DNS server still matches it. */
|
||||
|
||||
if (s->link)
|
||||
link_next_dns_server(s->link);
|
||||
link_next_dns_server(s->link, if_current);
|
||||
else
|
||||
manager_next_dns_server(s->manager);
|
||||
manager_next_dns_server(s->manager, if_current);
|
||||
}
|
||||
|
||||
void dns_scope_packet_received(DnsScope *s, usec_t rtt) {
|
||||
|
@ -80,7 +80,7 @@ bool dns_scope_good_key(DnsScope *s, const DnsResourceKey *key);
|
||||
|
||||
DnsServer *dns_scope_get_dns_server(DnsScope *s);
|
||||
unsigned dns_scope_get_n_dns_servers(DnsScope *s);
|
||||
void dns_scope_next_dns_server(DnsScope *s);
|
||||
void dns_scope_next_dns_server(DnsScope *s, DnsServer *if_current);
|
||||
|
||||
int dns_scope_llmnr_membership(DnsScope *s, bool b);
|
||||
int dns_scope_mdns_membership(DnsScope *s, bool b);
|
||||
|
@ -771,23 +771,25 @@ DnsServer *manager_get_dns_server(Manager *m) {
|
||||
return m->current_dns_server;
|
||||
}
|
||||
|
||||
void manager_next_dns_server(Manager *m) {
|
||||
void manager_next_dns_server(Manager *m, DnsServer *if_current) {
|
||||
assert(m);
|
||||
|
||||
/* If there's currently no DNS server set, then the next
|
||||
* manager_get_dns_server() will find one */
|
||||
/* If the DNS server is already a different one than the one specified in 'if_current' don't do anything */
|
||||
if (if_current && m->current_dns_server != if_current)
|
||||
return;
|
||||
|
||||
/* If there's currently no DNS server set, then the next manager_get_dns_server() will find one */
|
||||
if (!m->current_dns_server)
|
||||
return;
|
||||
|
||||
/* Change to the next one, but make sure to follow the linked
|
||||
* list only if the server is still linked. */
|
||||
/* Change to the next one, but make sure to follow the linked list only if the server is still
|
||||
* linked. */
|
||||
if (m->current_dns_server->linked && m->current_dns_server->servers_next) {
|
||||
manager_set_dns_server(m, m->current_dns_server->servers_next);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there was no next one, then start from the beginning of
|
||||
* the list */
|
||||
/* If there was no next one, then start from the beginning of the list */
|
||||
if (m->current_dns_server->type == DNS_SERVER_FALLBACK)
|
||||
manager_set_dns_server(m, m->fallback_dns_servers);
|
||||
else
|
||||
|
@ -143,7 +143,7 @@ DnsServer *manager_get_first_dns_server(Manager *m, DnsServerType t);
|
||||
|
||||
DnsServer *manager_set_dns_server(Manager *m, DnsServer *s);
|
||||
DnsServer *manager_get_dns_server(Manager *m);
|
||||
void manager_next_dns_server(Manager *m);
|
||||
void manager_next_dns_server(Manager *m, DnsServer *if_current);
|
||||
|
||||
DnssecMode dns_server_get_dnssec_mode(DnsServer *s);
|
||||
DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s);
|
||||
|
@ -484,7 +484,7 @@ static void dns_transaction_retry(DnsTransaction *t, bool next_server) {
|
||||
|
||||
/* Before we try again, switch to a new server. */
|
||||
if (next_server)
|
||||
dns_scope_next_dns_server(t->scope);
|
||||
dns_scope_next_dns_server(t->scope, t->server);
|
||||
|
||||
r = dns_transaction_go(t);
|
||||
if (r < 0)
|
||||
@ -1859,7 +1859,7 @@ int dns_transaction_go(DnsTransaction *t) {
|
||||
/* One of our own stub listeners */
|
||||
log_debug_errno(r, "Detected that specified DNS server is our own extra listener, switching DNS servers.");
|
||||
|
||||
dns_scope_next_dns_server(t->scope);
|
||||
dns_scope_next_dns_server(t->scope, t->server);
|
||||
|
||||
if (dns_scope_get_dns_server(t->scope) == t->server) {
|
||||
log_debug_errno(r, "Still pointing to extra listener after switching DNS servers, refusing operation.");
|
||||
@ -1890,7 +1890,7 @@ int dns_transaction_go(DnsTransaction *t) {
|
||||
return r;
|
||||
|
||||
/* Couldn't send? Try immediately again, with a new server */
|
||||
dns_scope_next_dns_server(t->scope);
|
||||
dns_scope_next_dns_server(t->scope, t->server);
|
||||
|
||||
return dns_transaction_go(t);
|
||||
}
|
||||
|
@ -731,19 +731,27 @@ DnsServer *link_get_dns_server(Link *l) {
|
||||
return l->current_dns_server;
|
||||
}
|
||||
|
||||
void link_next_dns_server(Link *l) {
|
||||
void link_next_dns_server(Link *l, DnsServer *if_current) {
|
||||
assert(l);
|
||||
|
||||
/* If the current server of the transaction is specified, and we already are at a different one,
|
||||
* don't do anything */
|
||||
if (if_current && l->current_dns_server != if_current)
|
||||
return;
|
||||
|
||||
/* If currently have no DNS server, then don't do anything, we'll pick it lazily the next time a DNS
|
||||
* server is needed. */
|
||||
if (!l->current_dns_server)
|
||||
return;
|
||||
|
||||
/* Change to the next one, but make sure to follow the linked
|
||||
* list only if this server is actually still linked. */
|
||||
/* Change to the next one, but make sure to follow the linked list only if this server is actually
|
||||
* still linked. */
|
||||
if (l->current_dns_server->linked && l->current_dns_server->servers_next) {
|
||||
link_set_dns_server(l, l->current_dns_server->servers_next);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pick the first one again, after we reached the end */
|
||||
link_set_dns_server(l, l->dns_servers);
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ void link_allocate_scopes(Link *l);
|
||||
|
||||
DnsServer* link_set_dns_server(Link *l, DnsServer *s);
|
||||
DnsServer* link_get_dns_server(Link *l);
|
||||
void link_next_dns_server(Link *l);
|
||||
void link_next_dns_server(Link *l, DnsServer *if_current);
|
||||
|
||||
DnssecMode link_get_dnssec_mode(Link *l);
|
||||
bool link_dnssec_supported(Link *l);
|
||||
|
Loading…
Reference in New Issue
Block a user