From ed318e8774757c39da5dd0ca9baa5b69ba185d76 Mon Sep 17 00:00:00 2001 From: Mary Strodl Date: Wed, 12 Jun 2024 14:20:21 -0400 Subject: [PATCH] connectivity: Add a timeout option to connectivity checks Adds an option in the connectivity section to change the timeout before the interface is deemed "limited". Previously, it was hardcoded to 20 seconds, but for our usecase (failing over to cell modem if hardwired ethernet drops), it's nice to be able to failover to another interface more quickly. --- NEWS | 1 + man/NetworkManager.conf.xml | 6 +++++ src/core/nm-config-data.c | 33 +++++++++++++++++++++++ src/core/nm-config-data.h | 2 ++ src/core/nm-config.c | 1 + src/core/nm-config.h | 1 + src/core/nm-connectivity.c | 10 ++++++- src/core/tests/config/NetworkManager.conf | 1 + src/core/tests/config/test-config.c | 3 +++ src/libnm-base/nm-config-base.h | 1 + 10 files changed, 58 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 716b90546a..91c72bb323 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ the later release. USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE! * Support matching a OVS system interface by MAC address. +* Add a timeout option to connectivity checking. ============================================= NetworkManager-1.48 diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml index 36e10061de..e368cf8fdb 100644 --- a/man/NetworkManager.conf.xml +++ b/man/NetworkManager.conf.xml @@ -1480,6 +1480,12 @@ managed=1 set to 0 connectivity checking is disabled. If missing, the default is 300 seconds. + + timeout + Specified in seconds; controls how long + to wait for a response before connectivity is marked as + limited. If missing, the default is 20 seconds. + response If set, controls what body content diff --git a/src/core/nm-config-data.c b/src/core/nm-config-data.c index 5b330f24d6..ef514bc76b 100644 --- a/src/core/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -62,6 +62,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_CONFIG_MAIN_FILE, PROP_CONNECTIVITY_ENABLED, PROP_CONNECTIVITY_URI, PROP_CONNECTIVITY_INTERVAL, + PROP_CONNECTIVITY_TIMEOUT, PROP_CONNECTIVITY_RESPONSE, PROP_NO_AUTO_DEFAULT, ); @@ -86,6 +87,7 @@ typedef struct { char *uri; char *response; guint interval; + guint timeout; } connectivity; int autoconnect_retries_default; @@ -304,6 +306,14 @@ nm_config_data_get_connectivity_interval(const NMConfigData *self) return NM_CONFIG_DATA_GET_PRIVATE(self)->connectivity.interval; } +guint +nm_config_data_get_connectivity_timeout(const NMConfigData *self) +{ + g_return_val_if_fail(self, 0); + + return NM_CONFIG_DATA_GET_PRIVATE(self)->connectivity.timeout; +} + const char * nm_config_data_get_connectivity_response(const NMConfigData *self) { @@ -2006,6 +2016,8 @@ nm_config_data_diff(NMConfigData *old_data, NMConfigData *new_data) != nm_config_data_get_connectivity_enabled(new_data) || nm_config_data_get_connectivity_interval(old_data) != nm_config_data_get_connectivity_interval(new_data) + || nm_config_data_get_connectivity_timeout(old_data) + != nm_config_data_get_connectivity_timeout(new_data) || !nm_streq0(nm_config_data_get_connectivity_uri(old_data), nm_config_data_get_connectivity_uri(new_data)) || !nm_streq0(nm_config_data_get_connectivity_response(old_data), @@ -2079,6 +2091,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) case PROP_CONNECTIVITY_INTERVAL: g_value_set_uint(value, nm_config_data_get_connectivity_interval(self)); break; + case PROP_CONNECTIVITY_TIMEOUT: + g_value_set_uint(value, nm_config_data_get_connectivity_timeout(self)); + break; case PROP_CONNECTIVITY_RESPONSE: g_value_set_string(value, nm_config_data_get_connectivity_response(self)); break; @@ -2221,6 +2236,15 @@ constructed(GObject *object) NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL); g_free(str); + /* On missing or invalid config value, fallback to 20. */ + str = g_key_file_get_string(priv->keyfile, + NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, + NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_TIMEOUT, + NULL); + priv->connectivity.timeout = + _nm_utils_ascii_str_to_int64(str, 10, 0, G_MAXUINT, NM_CONFIG_DEFAULT_CONNECTIVITY_TIMEOUT); + g_free(str); + priv->dns_mode = nm_strstrip(g_key_file_get_string(priv->keyfile, NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_DNS, @@ -2420,6 +2444,15 @@ nm_config_data_class_init(NMConfigDataClass *config_class) 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_CONNECTIVITY_TIMEOUT] = + g_param_spec_uint(NM_CONFIG_DATA_CONNECTIVITY_TIMEOUT, + "", + "", + 0, + G_MAXUINT, + 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_CONNECTIVITY_RESPONSE] = g_param_spec_string(NM_CONFIG_DATA_CONNECTIVITY_RESPONSE, "", diff --git a/src/core/nm-config-data.h b/src/core/nm-config-data.h index 0344ce9055..5eaf458f99 100644 --- a/src/core/nm-config-data.h +++ b/src/core/nm-config-data.h @@ -47,6 +47,7 @@ typedef enum { #define NM_CONFIG_DATA_CONNECTIVITY_ENABLED "connectivity-enabled" #define NM_CONFIG_DATA_CONNECTIVITY_URI "connectivity-uri" #define NM_CONFIG_DATA_CONNECTIVITY_INTERVAL "connectivity-interval" +#define NM_CONFIG_DATA_CONNECTIVITY_TIMEOUT "connectivity-timeout" #define NM_CONFIG_DATA_CONNECTIVITY_RESPONSE "connectivity-response" #define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default" #define NM_CONFIG_DATA_DNS_MODE "dns" @@ -172,6 +173,7 @@ char **nm_config_data_get_plugins(const NMConfigData *config_data, gboolean gboolean nm_config_data_get_connectivity_enabled(const NMConfigData *config_data); const char *nm_config_data_get_connectivity_uri(const NMConfigData *config_data); guint nm_config_data_get_connectivity_interval(const NMConfigData *config_data); +guint nm_config_data_get_connectivity_timeout(const NMConfigData *config_data); const char *nm_config_data_get_connectivity_response(const NMConfigData *config_data); int nm_config_data_get_autoconnect_retries_default(const NMConfigData *config_data); diff --git a/src/core/nm-config.c b/src/core/nm-config.c index 43eb364699..878f343a54 100644 --- a/src/core/nm-config.c +++ b/src/core/nm-config.c @@ -871,6 +871,7 @@ static const ConfigGroup config_groups[] = { .group = NM_CONFIG_KEYFILE_GROUP_CONNECTIVITY, .keys = NM_MAKE_STRV(NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_ENABLED, NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_INTERVAL, + NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_TIMEOUT, NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_RESPONSE, NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_URI, ), }, diff --git a/src/core/nm-config.h b/src/core/nm-config.h index e65582c34a..5518184ce3 100644 --- a/src/core/nm-config.h +++ b/src/core/nm-config.h @@ -28,6 +28,7 @@ #define NM_CONFIG_SIGNAL_CONFIG_CHANGED "config-changed" #define NM_CONFIG_DEFAULT_CONNECTIVITY_INTERVAL 300 +#define NM_CONFIG_DEFAULT_CONNECTIVITY_TIMEOUT 20 #define NM_CONFIG_DEFAULT_CONNECTIVITY_RESPONSE "NetworkManager is online" /* NOT LOCALIZED */ typedef struct NMConfigCmdLineOptions NMConfigCmdLineOptions; diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c index 15dc31aa24..65eec36d6d 100644 --- a/src/core/nm-connectivity.c +++ b/src/core/nm-connectivity.c @@ -56,6 +56,7 @@ typedef struct { char *host; char *port; char *response; + guint timeout; } ConConfig; struct _NMConnectivityCheckHandle { @@ -738,7 +739,9 @@ do_curl_request(NMConnectivityCheckHandle *cb_data, const char *hosts) cb_data->concheck.curl_mhandle = mhandle; cb_data->concheck.curl_ehandle = ehandle; cb_data->concheck.request_headers = curl_slist_append(NULL, "Connection: close"); - cb_data->timeout_source = nm_g_timeout_add_seconds_source(20, _timeout_cb, cb_data); + cb_data->timeout_source = nm_g_timeout_add_seconds_source(cb_data->concheck.con_config->timeout, + _timeout_cb, + cb_data); curl_multi_setopt(mhandle, CURLMOPT_SOCKETFUNCTION, multi_socket_cb); curl_multi_setopt(mhandle, CURLMOPT_SOCKETDATA, cb_data); @@ -1226,6 +1229,7 @@ update_config(NMConnectivity *self, NMConfigData *config_data) { NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE(self); guint interval; + guint new_timeout; gboolean enabled; gboolean changed = FALSE; const char *cur_uri = priv->con_config ? priv->con_config->uri : NULL; @@ -1237,6 +1241,8 @@ update_config(NMConnectivity *self, NMConfigData *config_data) gs_free char *new_host = NULL; gs_free char *new_port = NULL; + new_timeout = nm_config_data_get_connectivity_timeout(config_data); + new_uri = nm_config_data_get_connectivity_uri(config_data); if (!nm_streq0(new_uri, cur_uri)) { new_uri_valid = (new_uri && *new_uri); @@ -1277,6 +1283,7 @@ update_config(NMConnectivity *self, NMConfigData *config_data) changed = TRUE; if (!priv->con_config || !nm_streq0(new_uri, priv->con_config->uri) + || new_timeout != priv->con_config->timeout || !nm_streq0(new_response, priv->con_config->response)) { if (!new_host_port) { new_host = priv->con_config ? g_strdup(priv->con_config->host) : NULL; @@ -1290,6 +1297,7 @@ update_config(NMConnectivity *self, NMConfigData *config_data) .response = g_strdup(new_response), .host = g_steal_pointer(&new_host), .port = g_steal_pointer(&new_port), + .timeout = new_timeout, }; } priv->uri_valid = new_uri_valid; diff --git a/src/core/tests/config/NetworkManager.conf b/src/core/tests/config/NetworkManager.conf index a447b6d68d..ae9f3e46b5 100644 --- a/src/core/tests/config/NetworkManager.conf +++ b/src/core/tests/config/NetworkManager.conf @@ -9,6 +9,7 @@ level=INFO [connectivity] uri=http://example.com interval=100 +timeout=42 response=Hello [extra-section] diff --git a/src/core/tests/config/test-config.c b/src/core/tests/config/test-config.c index 2b27d53549..8365fc8232 100644 --- a/src/core/tests/config/test-config.c +++ b/src/core/tests/config/test-config.c @@ -167,6 +167,9 @@ test_config_simple(void) g_assert_cmpint(nm_config_data_get_connectivity_interval(nm_config_get_data_orig(config)), ==, 100); + g_assert_cmpint(nm_config_data_get_connectivity_timeout(nm_config_get_data_orig(config)), + ==, + 42); plugins = nm_config_data_get_plugins(nm_config_get_data_orig(config), FALSE); g_assert_cmpint(g_strv_length((char **) plugins), ==, 3); diff --git a/src/libnm-base/nm-config-base.h b/src/libnm-base/nm-config-base.h index 6d050ae176..362a183c93 100644 --- a/src/libnm-base/nm-config-base.h +++ b/src/libnm-base/nm-config-base.h @@ -44,6 +44,7 @@ #define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_ENABLED "enabled" #define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_INTERVAL "interval" +#define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_TIMEOUT "timeout" #define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_RESPONSE "response" #define NM_CONFIG_KEYFILE_KEY_CONNECTIVITY_URI "uri"