summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Maximets <i.maximets@ovn.org>2022-03-10 23:33:17 +0100
committerIlya Maximets <i.maximets@ovn.org>2022-03-30 16:59:55 +0200
commit73d32a67c1133a4e02728612cee023da55e56e58 (patch)
tree4591a7bc396bc4e03611d26fc315af67214c0a45
parent223e47f417dea762563ea77e2de2c88540bfd46a (diff)
downloadopenvswitch-73d32a67c1133a4e02728612cee023da55e56e58.tar.gz
ovsdb: raft: Fix inability to read the database with DNS host names.
Clustered OVSDB allows to use DNS names as addresses of raft members. However, if DNS resolution fails during the initial database read, this causes a fatal failure and exit of the ovsdb-server process. Also, if DNS name of a joining server is not resolvable for one of the followers, this follower will reject append requests for a new server to join until the name is successfully resolved. This makes a follower effectively non-functional while DNS is unavailable. To fix the problem relax the address verification. Allowing validation to pass if only name resolution failed and the address is valid otherwise. This will allow addresses to be added to the database, so connections could be established later when the DNS is available. Additionally fixing missed initialization of the dns-resolve module. Without it, DNS requests are blocking. This causes unexpected delays in runtime. Fixes: 771680d96fb6 ("DNS: Add basic support for asynchronous DNS resolving") Reported-at: https://bugzilla.redhat.com/2055097 Acked-by: Dumitru Ceara <dceara@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
-rw-r--r--lib/dns-resolve.c2
-rw-r--r--lib/socket-util.c39
-rw-r--r--lib/socket-util.h3
-rw-r--r--lib/stream.c2
-rw-r--r--ofproto/ofproto-dpif-sflow.c3
-rw-r--r--ovsdb/ovsdb-server.c3
-rw-r--r--ovsdb/raft-private.c5
7 files changed, 39 insertions, 18 deletions
diff --git a/lib/dns-resolve.c b/lib/dns-resolve.c
index 1ff58960f..6a6b24d98 100644
--- a/lib/dns-resolve.c
+++ b/lib/dns-resolve.c
@@ -253,7 +253,7 @@ resolve_callback__(void *req_, int err, struct ub_result *result)
if (err != 0 || (result->qtype == ns_t_aaaa && !result->havedata)) {
ub_resolve_free(result);
req->state = RESOLVE_ERROR;
- VLOG_ERR_RL(&rl, "%s: failed to resolve", req->name);
+ VLOG_WARN_RL(&rl, "%s: failed to resolve", req->name);
return;
}
diff --git a/lib/socket-util.c b/lib/socket-util.c
index 4f1ffecf5..38705cc51 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -62,7 +62,8 @@ static bool parse_sockaddr_components(struct sockaddr_storage *ss,
const char *port_s,
uint16_t default_port,
const char *s,
- bool resolve_host);
+ bool resolve_host,
+ bool *dns_failure);
/* Sets 'fd' to non-blocking mode. Returns 0 if successful, otherwise a
* positive errno value. */
@@ -438,7 +439,7 @@ parse_sockaddr_components_dns(struct sockaddr_storage *ss OVS_UNUSED,
dns_resolve(host_s, &tmp_host_s);
if (tmp_host_s != NULL) {
parse_sockaddr_components(ss, tmp_host_s, port_s,
- default_port, s, false);
+ default_port, s, false, NULL);
free(tmp_host_s);
return true;
}
@@ -450,11 +451,15 @@ parse_sockaddr_components(struct sockaddr_storage *ss,
char *host_s,
const char *port_s, uint16_t default_port,
const char *s,
- bool resolve_host)
+ bool resolve_host, bool *dns_failure)
{
struct sockaddr_in *sin = sin_cast(sa_cast(ss));
int port;
+ if (dns_failure) {
+ *dns_failure = false;
+ }
+
if (port_s && port_s[0]) {
if (!str_to_int(port_s, 10, &port) || port < 0 || port > 65535) {
VLOG_ERR("%s: bad port number \"%s\"", s, port_s);
@@ -501,10 +506,15 @@ parse_sockaddr_components(struct sockaddr_storage *ss,
return true;
resolve:
- if (resolve_host && parse_sockaddr_components_dns(ss, host_s, port_s,
- default_port, s)) {
- return true;
- } else if (!resolve_host) {
+ if (resolve_host) {
+ if (parse_sockaddr_components_dns(ss, host_s, port_s,
+ default_port, s)) {
+ return true;
+ }
+ if (dns_failure) {
+ *dns_failure = true;
+ }
+ } else {
VLOG_ERR("%s: bad IP address \"%s\"", s, host_s);
}
exit:
@@ -521,10 +531,12 @@ exit:
* It resolves the host if 'resolve_host' is true.
*
* On success, returns true and stores the parsed remote address into '*ss'.
- * On failure, logs an error, stores zeros into '*ss', and returns false. */
+ * On failure, logs an error, stores zeros into '*ss', and returns false,
+ * '*dns_failure' indicates if the host resolution failed. */
bool
inet_parse_active(const char *target_, int default_port,
- struct sockaddr_storage *ss, bool resolve_host)
+ struct sockaddr_storage *ss,
+ bool resolve_host, bool *dns_failure)
{
char *target = xstrdup(target_);
char *port, *host;
@@ -539,7 +551,7 @@ inet_parse_active(const char *target_, int default_port,
ok = false;
} else {
ok = parse_sockaddr_components(ss, host, port, default_port,
- target_, resolve_host);
+ target_, resolve_host, dns_failure);
}
if (!ok) {
memset(ss, 0, sizeof *ss);
@@ -576,7 +588,7 @@ inet_open_active(int style, const char *target, int default_port,
int error;
/* Parse. */
- if (!inet_parse_active(target, default_port, &ss, true)) {
+ if (!inet_parse_active(target, default_port, &ss, true, NULL)) {
error = EAFNOSUPPORT;
goto exit;
}
@@ -660,7 +672,7 @@ inet_parse_passive(const char *target_, int default_port,
ok = false;
} else {
ok = parse_sockaddr_components(ss, host, port, default_port,
- target_, true);
+ target_, true, NULL);
}
if (!ok) {
memset(ss, 0, sizeof *ss);
@@ -783,7 +795,8 @@ inet_parse_address(const char *target_, struct sockaddr_storage *ss)
{
char *target = xstrdup(target_);
char *host = unbracket(target);
- bool ok = parse_sockaddr_components(ss, host, NULL, 0, target_, false);
+ bool ok = parse_sockaddr_components(ss, host, NULL, 0,
+ target_, false, NULL);
if (!ok) {
memset(ss, 0, sizeof *ss);
}
diff --git a/lib/socket-util.h b/lib/socket-util.h
index 9ccb7d4cc..bf66393df 100644
--- a/lib/socket-util.h
+++ b/lib/socket-util.h
@@ -49,7 +49,8 @@ ovs_be32 guess_netmask(ovs_be32 ip);
void inet_parse_host_port_tokens(char *s, char **hostp, char **portp);
void inet_parse_port_host_tokens(char *s, char **portp, char **hostp);
bool inet_parse_active(const char *target, int default_port,
- struct sockaddr_storage *ssp, bool resolve_host);
+ struct sockaddr_storage *ssp,
+ bool resolve_host, bool *dns_failure);
int inet_open_active(int style, const char *target, int default_port,
struct sockaddr_storage *ssp, int *fdp, uint8_t dscp);
diff --git a/lib/stream.c b/lib/stream.c
index e246b3773..99559fde9 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -763,7 +763,7 @@ stream_parse_target_with_default_port(const char *target, int default_port,
struct sockaddr_storage *ss)
{
return ((!strncmp(target, "tcp:", 4) || !strncmp(target, "ssl:", 4))
- && inet_parse_active(target + 4, default_port, ss, true));
+ && inet_parse_active(target + 4, default_port, ss, true, NULL));
}
/* Attempts to guess the content type of a stream whose first few bytes were
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index b39482dbf..1681ba34a 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -468,7 +468,8 @@ sflow_choose_agent_address(const char *agent_device,
const char *target;
SSET_FOR_EACH (target, targets) {
struct sockaddr_storage ss;
- if (inet_parse_active(target, SFL_DEFAULT_COLLECTOR_PORT, &ss, true)) {
+ if (inet_parse_active(target, SFL_DEFAULT_COLLECTOR_PORT,
+ &ss, true, NULL)) {
/* sFlow only supports target in default routing table with
* packet mark zero.
*/
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index 2bc0a6906..ef558efb3 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -26,6 +26,7 @@
#include "command-line.h"
#include "daemon.h"
#include "dirs.h"
+#include "dns-resolve.h"
#include "openvswitch/dynamic-string.h"
#include "fatal-signal.h"
#include "file.h"
@@ -318,6 +319,7 @@ main(int argc, char *argv[])
service_start(&argc, &argv);
fatal_ignore_sigpipe();
process_init();
+ dns_resolve_init(true);
bool active = false;
parse_options(argc, argv, &db_filenames, &remotes, &unixctl_path,
@@ -497,6 +499,7 @@ main(int argc, char *argv[])
run_command, process_status_msg(status));
}
}
+ dns_resolve_destroy();
perf_counters_destroy();
service_stop();
return 0;
diff --git a/ovsdb/raft-private.c b/ovsdb/raft-private.c
index 26d39a087..7b7bcd74a 100644
--- a/ovsdb/raft-private.c
+++ b/ovsdb/raft-private.c
@@ -33,7 +33,10 @@ raft_address_validate(const char *address)
return NULL;
} else if (!strncmp(address, "ssl:", 4) || !strncmp(address, "tcp:", 4)) {
struct sockaddr_storage ss;
- if (!inet_parse_active(address + 4, -1, &ss, true)) {
+ bool dns_failure = false;
+
+ if (!inet_parse_active(address + 4, -1, &ss, true, &dns_failure)
+ && !dns_failure) {
return ovsdb_error(NULL, "%s: syntax error in address", address);
}
return NULL;