summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/devices/nm-device.c344
-rw-r--r--src/devices/nm-device.h2
-rw-r--r--src/main.c2
-rw-r--r--src/nm-connectivity.c33
-rw-r--r--src/nm-connectivity.h4
-rw-r--r--src/nm-manager.c51
6 files changed, 354 insertions, 82 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 6142908a57..cc3df54ae8 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -164,6 +164,7 @@ struct _NMDeviceConnectivityHandle {
gpointer user_data;
NMConnectivityCheckHandle *c_handle;
guint64 seq;
+ bool is_periodic:1;
};
/*****************************************************************************/
@@ -543,7 +544,19 @@ typedef struct _NMDevicePrivate {
NMConnectivity *concheck_mgr;
- gulong concheck_periodic_id;
+ /* if periodic checks are enabled, this is the source id for the next check. */
+ guint concheck_p_cur_id;
+
+ /* the currently configured max periodic interval. */
+ guint concheck_p_max_interval;
+
+ /* the current interval. If we are probing, the interval might be lower
+ * then the configured max interval. */
+ guint concheck_p_cur_interval;
+
+ /* the timestamp, when we last scheduled the timer concheck_p_cur_id with current interval
+ * concheck_p_cur_interval. */
+ gint64 concheck_p_cur_basetime_ns;
NMConnectivityState connectivity_state;
@@ -2185,17 +2198,225 @@ nm_device_get_physical_port_id (NMDevice *self)
/*****************************************************************************/
+typedef enum {
+ CONCHECK_SCHEDULE_UPDATE_INTERVAL,
+ CONCHECK_SCHEDULE_CHECK_EXTERNAL,
+ CONCHECK_SCHEDULE_CHECK_PERIODIC,
+ CONCHECK_SCHEDULE_RETURNED_MIN,
+ CONCHECK_SCHEDULE_RETURNED_BUMP,
+ CONCHECK_SCHEDULE_RETURNED_MAX,
+} ConcheckScheduleMode;
+
+static NMDeviceConnectivityHandle *concheck_start (NMDevice *self,
+ NMDeviceConnectivityCallback callback,
+ gpointer user_data,
+ gboolean is_periodic);
+
+static void concheck_periodic_schedule_set (NMDevice *self,
+ ConcheckScheduleMode mode);
+
+static gboolean
+concheck_periodic_timeout_cb (gpointer user_data)
+{
+ NMDevice *self = user_data;
+
+ concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_CHECK_PERIODIC);
+ concheck_start (self, NULL, NULL, TRUE);
+ return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+concheck_is_possible (NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+ if ( !nm_device_is_real (self)
+ || NM_FLAGS_HAS (priv->unmanaged_flags, NM_UNMANAGED_LOOPBACK))
+ return FALSE;
+
+ /* we enable periodic checks for every device state (except UNKNOWN). Especially with
+ * unmanaged devices, it is interesting to know whether we have connectivity on that device. */
+ if (priv->state == NM_DEVICE_STATE_UNKNOWN)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+concheck_periodic_schedule_do (NMDevice *self, gint64 interval_ns)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ gboolean periodic_check_disabled = FALSE;
+
+ /* we always cancel whatever was pending. */
+ if (nm_clear_g_source (&priv->concheck_p_cur_id))
+ periodic_check_disabled = TRUE;
+
+ if (priv->concheck_p_max_interval == 0) {
+ /* periodic checks are disabled */
+ goto out;
+ }
+
+ nm_assert (interval_ns >= 0);
+
+ if (!concheck_is_possible (self))
+ goto out;
+
+ _LOGT (LOGD_CONCHECK, "connectivity: periodic-check: %sscheduled in %u milliseconds (%u seconds interval)",
+ periodic_check_disabled ? "re-" : "",
+ (guint) (interval_ns / NM_UTILS_NS_PER_MSEC),
+ priv->concheck_p_cur_interval);
+
+ nm_assert (priv->concheck_p_cur_interval > 0);
+ priv->concheck_p_cur_id = g_timeout_add (interval_ns / NM_UTILS_NS_PER_MSEC,
+ concheck_periodic_timeout_cb,
+ self);
+ return TRUE;
+out:
+ if (periodic_check_disabled)
+ _LOGT (LOGD_CONCHECK, "connectivity: periodic-check: unscheduled");
+ return FALSE;
+}
+
+#define CONCHECK_P_PROBE_INTERVAL 1
+
static void
-concheck_update_state (NMDevice *self, NMConnectivityState state)
+concheck_periodic_schedule_set (NMDevice *self,
+ ConcheckScheduleMode mode)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ gint64 new_expiry, cur_expiry, tdiff;
+ gint64 now_ns = 0;
- if (state == NM_CONNECTIVITY_ERROR)
+ if (priv->concheck_p_max_interval == 0) {
+ /* periodic check is disabled. Nothing to do. */
return;
+ }
- /* If the connectivity check is disabled and we obtain a fake
- * result, make an optimistic guess. */
- if (state == NM_CONNECTIVITY_FAKE) {
+ if (!priv->concheck_p_cur_id) {
+ /* we currently don't have a timeout scheduled. No need to reschedule
+ * another one... */
+ if (mode == CONCHECK_SCHEDULE_UPDATE_INTERVAL) {
+ /* ... unless, we are initalizing. In this case, setup the current current
+ * interval and schedule a perform a check right away. */
+ priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_max_interval, CONCHECK_P_PROBE_INTERVAL);
+ priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
+ if (concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND))
+ concheck_start (self, NULL, NULL, TRUE);
+ }
+ return;
+ }
+
+ switch (mode) {
+ case CONCHECK_SCHEDULE_UPDATE_INTERVAL:
+ /* called with "UPDATE_INTERVAL" and already have a concheck_p_cur_id scheduled. */
+
+ if (priv->concheck_p_cur_interval <= priv->concheck_p_max_interval) {
+ /* we currently have a shorter interval set, then what we now have. Either,
+ * because we are probing, or because the previous max interval was shorter.
+ *
+ * Either way, the current timer is set just fine. Nothing to do. */
+ return;
+ }
+
+ cur_expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_max_interval * NM_UTILS_NS_PER_SECOND);
+ priv->concheck_p_cur_interval = priv->concheck_p_max_interval;
+ priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
+ if (cur_expiry <= now_ns) {
+ /* the last timer was scheduled longer ago then the new desired interval. It means,
+ * we must schedule a timer right away */
+ if (concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND)) {
+ concheck_start (self, NULL, NULL, TRUE);
+ }
+ } else {
+ /* we only need to reset the timer. */
+ concheck_periodic_schedule_do (self, (cur_expiry - now_ns) / NM_UTILS_NS_PER_MSEC);
+ }
+ return;
+
+ case CONCHECK_SCHEDULE_CHECK_EXTERNAL:
+ /* a external connectivity check delays our periodic check. We reset the counter. */
+ priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
+ concheck_periodic_schedule_do (self, priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
+ return;
+
+ case CONCHECK_SCHEDULE_CHECK_PERIODIC:
+ /* we schedule a periodic connectivity check now. We just remember the time when
+ * we did it. There is nothing to reschedule, it's fine already. */
+ priv->concheck_p_cur_basetime_ns = nm_utils_get_monotonic_timestamp_ns_cached (&now_ns);
+ return;
+
+ /* we just got an event that we lost connectivity (that is, concheck returned). We reset
+ * the interval to min/max or increase the probe interval (bump). */
+ case CONCHECK_SCHEDULE_RETURNED_MIN:
+ priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_max_interval, CONCHECK_P_PROBE_INTERVAL);
+ break;
+ case CONCHECK_SCHEDULE_RETURNED_MAX:
+ priv->concheck_p_cur_interval = priv->concheck_p_max_interval;
+ break;
+ case CONCHECK_SCHEDULE_RETURNED_BUMP:
+ priv->concheck_p_cur_interval = NM_MIN (priv->concheck_p_cur_interval * 2, priv->concheck_p_max_interval);
+ break;
+ }
+
+ /* we are here, because we returned from a connectivity check and adjust the current interval.
+ *
+ * But note that we calculate the new timeout based on the time when we scheduled the
+ * last check, instead of counting from now. The reaons is, that we want that the times
+ * when we schedule checks be at precise intervals, without including the time it took for
+ * the connectivity check. */
+ new_expiry = priv->concheck_p_cur_basetime_ns + (priv->concheck_p_cur_interval * NM_UTILS_NS_PER_SECOND);
+ tdiff = NM_MAX (new_expiry - nm_utils_get_monotonic_timestamp_ns_cached (&now_ns), 0);
+ priv->concheck_p_cur_basetime_ns = now_ns - tdiff;
+ concheck_periodic_schedule_do (self, tdiff);
+}
+
+void
+nm_device_check_connectivity_update_interval (NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ guint new_interval;
+
+ new_interval = nm_connectivity_get_interval (concheck_get_mgr (self));
+
+ new_interval = NM_MIN (new_interval, 7 *24 * 3600);
+
+ if (new_interval != priv->concheck_p_max_interval) {
+ _LOGT (LOGD_CONCHECK, "connectivity: periodic-check: set interval to %u seconds", new_interval);
+ priv->concheck_p_max_interval = new_interval;
+ }
+
+ if (!new_interval) {
+ /* this will cancel any potentially pending timeout. */
+ concheck_periodic_schedule_do (self, 0);
+ return;
+ }
+
+ concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_UPDATE_INTERVAL);
+}
+
+static void
+concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_periodic)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+
+ /* @state is a result of the connectivity check. We only expect a precise
+ * number of possible values. */
+ nm_assert (NM_IN_SET (state, NM_CONNECTIVITY_LIMITED,
+ NM_CONNECTIVITY_PORTAL,
+ NM_CONNECTIVITY_FULL,
+ NM_CONNECTIVITY_FAKE,
+ NM_CONNECTIVITY_ERROR));
+
+ if (state == NM_CONNECTIVITY_ERROR) {
+ /* on error, we don't change the current connectivity state,
+ * except making UNKNOWN to NONE. */
+ state = priv->connectivity_state;
+ if (state == NM_CONNECTIVITY_UNKNOWN)
+ state = NM_CONNECTIVITY_NONE;
+ } else if (state == NM_CONNECTIVITY_FAKE) {
+ /* If the connectivity check is disabled and we obtain a fake
+ * result, make an optimistic guess. */
if (priv->state == NM_DEVICE_STATE_ACTIVATED) {
if (nm_device_get_best_default_route (self, AF_UNSPEC))
state = NM_CONNECTIVITY_FULL;
@@ -2205,10 +2426,32 @@ concheck_update_state (NMDevice *self, NMConnectivityState state)
state = NM_CONNECTIVITY_NONE;
}
- if (priv->connectivity_state == state)
+ if (priv->connectivity_state == state) {
+ /* we got a connectivty update, but the state didn't change. If we were probing,
+ * we bump the probe frequency. */
+ if ( is_periodic
+ && priv->concheck_p_cur_id)
+ concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_BUMP);
return;
+ }
+ /* we need to update the probe interval before emitting signals. Emitting
+ * a signal might call back into NMDevice and change the probe settings.
+ * So, do that first. */
+ if (state == NM_CONNECTIVITY_FULL) {
+ /* we reached full connectivity state. Stop probing by setting the
+ * interval to the max. */
+ concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_MAX);
+ } else if (priv->connectivity_state == NM_CONNECTIVITY_FULL) {
+ /* we are about to loose connectivity. (re)start probing by setting
+ * the timeout interval to the min. */
+ concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_MIN);
+ } else {
+ if ( is_periodic
+ && priv->concheck_p_cur_id)
+ concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_BUMP);
+ }
- _LOGD (LOGD_CONCHECK, "state changed from %s to %s",
+ _LOGD (LOGD_CONCHECK, "connectivity state changed from %s to %s",
nm_connectivity_state_to_string (priv->connectivity_state),
nm_connectivity_state_to_string (state));
priv->connectivity_state = state;
@@ -2227,34 +2470,6 @@ concheck_update_state (NMDevice *self, NMConnectivityState state)
}
static void
-concheck_periodic (NMConnectivity *connectivity, NMDevice *self)
-{
- nm_device_check_connectivity (self, NULL, NULL);
-}
-
-static void
-concheck_periodic_update (NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
-
- if ( priv->state == NM_DEVICE_STATE_ACTIVATED
- && nm_device_get_best_default_route (self, AF_UNSPEC)) {
- if (!priv->concheck_periodic_id) {
- priv->concheck_periodic_id = g_signal_connect (concheck_get_mgr (self),
- NM_CONNECTIVITY_PERIODIC_CHECK,
- G_CALLBACK (concheck_periodic), self);
- nm_device_check_connectivity (self, NULL, NULL);
- }
- } else {
- if (priv->concheck_periodic_id) {
- /* The default route has gone off, trigger a final connectivity check. */
- nm_clear_g_signal_handler (priv->concheck_mgr, &priv->concheck_periodic_id);
- nm_device_check_connectivity (self, NULL, NULL);
- }
- }
-}
-
-static void
concheck_handle_complete (NMDeviceConnectivityHandle *handle,
GError *error)
{
@@ -2264,7 +2479,7 @@ concheck_handle_complete (NMDeviceConnectivityHandle *handle,
c_list_unlink (&handle->concheck_lst);
if (handle->c_handle)
- nm_connectivity_check_cancel (g_steal_pointer (&handle->c_handle));
+ nm_connectivity_check_cancel (handle->c_handle);
if (handle->callback) {
handle->callback (handle->self,
@@ -2291,6 +2506,18 @@ concheck_cb (NMConnectivity *connectivity,
gboolean handle_is_alive;
guint64 seq;
+ handle = user_data;
+ nm_assert (handle->c_handle == c_handle);
+ nm_assert (NM_IS_DEVICE (handle->self));
+
+ handle->c_handle = NULL;
+ self = g_object_ref (handle->self);
+
+ _LOGT (LOGD_CONCHECK, "connectivity: complete check (seq:%llu, state:%s%s%s%s)",
+ (long long unsigned) handle->seq,
+ nm_connectivity_state_to_string (state),
+ NM_PRINT_FMT_QUOTED (error, ", error: ", error->message, "", ""));
+
if (nm_utils_error_is_cancelled (error, FALSE)) {
/* the only place where we nm_connectivity_check_cancel(@c_handle), is
* from inside concheck_handle_event(). This is a recursive call,
@@ -2301,12 +2528,7 @@ concheck_cb (NMConnectivity *connectivity,
/* we keep NMConnectivity instance alive. It cannot be disposing. */
nm_assert (!nm_utils_error_is_cancelled (error, TRUE));
- handle = user_data;
- nm_assert (handle->c_handle == c_handle);
- handle->c_handle = NULL;
-
/* keep @self alive, while we invoke callbacks. */
- self = g_object_ref (handle->self);
priv = NM_DEVICE_GET_PRIVATE (self);
nm_assert (!handle || c_list_contains (&priv->concheck_lst_head, &handle->concheck_lst));
@@ -2314,7 +2536,7 @@ concheck_cb (NMConnectivity *connectivity,
seq = handle->seq;
/* first update the new state, and emit signals. */
- concheck_update_state (self, state);
+ concheck_update_state (self, state, handle->is_periodic);
handle_is_alive = FALSE;
@@ -2361,10 +2583,11 @@ check_handles:
concheck_handle_complete (handle, NULL);
}
-NMDeviceConnectivityHandle *
-nm_device_check_connectivity (NMDevice *self,
- NMDeviceConnectivityCallback callback,
- gpointer user_data)
+static NMDeviceConnectivityHandle *
+concheck_start (NMDevice *self,
+ NMDeviceConnectivityCallback callback,
+ gpointer user_data,
+ gboolean is_periodic)
{
static guint64 seq_counter = 0;
NMDevicePrivate *priv;
@@ -2379,8 +2602,14 @@ nm_device_check_connectivity (NMDevice *self,
handle->self = self;
handle->callback = callback;
handle->user_data = user_data;
+ handle->is_periodic = is_periodic;
+
c_list_link_tail (&priv->concheck_lst_head, &handle->concheck_lst);
+ _LOGT (LOGD_CONCHECK, "connectivity: start check (seq:%llu%s)",
+ (long long unsigned) handle->seq,
+ is_periodic ? ", periodic-check" : "");
+
handle->c_handle = nm_connectivity_check_start (concheck_get_mgr (self),
nm_device_get_ip_iface (self),
concheck_cb,
@@ -2388,6 +2617,21 @@ nm_device_check_connectivity (NMDevice *self,
return handle;
}
+NMDeviceConnectivityHandle *
+nm_device_check_connectivity (NMDevice *self,
+ NMDeviceConnectivityCallback callback,
+ gpointer user_data)
+{
+ NMDeviceConnectivityHandle *handle;
+
+ if (!concheck_is_possible (self))
+ return NULL;
+
+ concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_CHECK_EXTERNAL);
+ handle = concheck_start (self, callback, user_data, FALSE);
+ return handle;
+}
+
void
nm_device_check_connectivity_cancel (NMDeviceConnectivityHandle *handle)
{
@@ -10688,8 +10932,6 @@ nm_device_set_ip_config (NMDevice *self,
}
if (IS_IPv4) {
- concheck_periodic_update (self);
-
if (!nm_device_sys_iface_state_is_external_or_assume (self))
ip4_rp_filter_update (self);
}
@@ -13544,7 +13786,7 @@ _set_state_full (NMDevice *self,
if (ip_config_valid (old_state) && !ip_config_valid (state))
notify_ip_properties (self);
- concheck_periodic_update (self);
+ nm_device_check_connectivity_update_interval (self);
/* Dispose of the cached activation request */
if (req)
@@ -14711,7 +14953,7 @@ dispose (GObject *object)
g_clear_object (&priv->lldp_listener);
}
- nm_clear_g_signal_handler (priv->concheck_mgr, &priv->concheck_periodic_id);
+ nm_clear_g_source (&priv->concheck_p_cur_id);
G_OBJECT_CLASS (nm_device_parent_class)->dispose (object);
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index 24d184657f..fd266d69ab 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -783,6 +783,8 @@ typedef void (*NMDeviceConnectivityCallback) (NMDevice *self,
GError *error,
gpointer user_data);
+void nm_device_check_connectivity_update_interval (NMDevice *self);
+
NMDeviceConnectivityHandle *nm_device_check_connectivity (NMDevice *self,
NMDeviceConnectivityCallback callback,
gpointer user_data);
diff --git a/src/main.c b/src/main.c
index 69902c8437..bd8e26a556 100644
--- a/src/main.c
+++ b/src/main.c
@@ -402,8 +402,6 @@ main (int argc, char *argv[])
manager))
goto done;
- NM_UTILS_KEEP_ALIVE (manager, nm_connectivity_get (), "NMManager-depends-on-NMConnectivity");
-
nm_dispatcher_init ();
g_signal_connect (manager, NM_MANAGER_CONFIGURE_QUIT, G_CALLBACK (manager_configure_quit), config);
diff --git a/src/nm-connectivity.c b/src/nm-connectivity.c
index 039ff71d05..d46b7d2859 100644
--- a/src/nm-connectivity.c
+++ b/src/nm-connectivity.c
@@ -81,7 +81,7 @@ struct _NMConnectivityCheckHandle {
};
enum {
- PERIODIC_CHECK,
+ CONFIG_CHANGED,
LAST_SIGNAL
};
@@ -99,7 +99,6 @@ typedef struct {
struct {
CURLM *curl_mhandle;
guint curl_timer;
- guint periodic_check_id;
} concheck;
#endif
} NMConnectivityPrivate;
@@ -539,21 +538,20 @@ nm_connectivity_check_cancel (NMConnectivityCheckHandle *cb_data)
gboolean
nm_connectivity_check_enabled (NMConnectivity *self)
{
- NMConnectivityPrivate *priv = NM_CONNECTIVITY_GET_PRIVATE (self);
+ g_return_val_if_fail (NM_IS_CONNECTIVITY (self), FALSE);
- return priv->enabled;
+ return NM_CONNECTIVITY_GET_PRIVATE (self)->enabled;
}
/*****************************************************************************/
-#if WITH_CONCHECK
-static gboolean
-periodic_check (gpointer user_data)
+guint
+nm_connectivity_get_interval (NMConnectivity *self)
{
- g_signal_emit (NM_CONNECTIVITY (user_data), signals[PERIODIC_CHECK], 0);
- return G_SOURCE_CONTINUE;
+ return nm_connectivity_check_enabled (self)
+ ? NM_CONNECTIVITY_GET_PRIVATE (self)->interval
+ : 0;
}
-#endif
static void
update_config (NMConnectivity *self, NMConfigData *config_data)
@@ -592,6 +590,7 @@ update_config (NMConnectivity *self, NMConfigData *config_data)
/* Set the interval. */
interval = nm_config_data_get_connectivity_interval (config_data);
+ interval = MIN (interval, (7 * 24 * 3600));
if (priv->interval != interval) {
priv->interval = interval;
changed = TRUE;
@@ -622,13 +621,8 @@ update_config (NMConnectivity *self, NMConfigData *config_data)
changed = TRUE;
}
-#if WITH_CONCHECK
- if (changed) {
- nm_clear_g_source (&priv->concheck.periodic_check_id);
- if (nm_connectivity_check_enabled (self))
- priv->concheck.periodic_check_id = g_timeout_add_seconds (priv->interval, periodic_check, self);
- }
-#endif
+ if (changed)
+ g_signal_emit (self, signals[CONFIG_CHANGED], 0);
}
static void
@@ -699,7 +693,6 @@ again:
curl_multi_cleanup (priv->concheck.curl_mhandle);
curl_global_cleanup ();
- nm_clear_g_source (&priv->concheck.periodic_check_id);
#endif
if (priv->config) {
@@ -715,8 +708,8 @@ nm_connectivity_class_init (NMConnectivityClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- signals[PERIODIC_CHECK] =
- g_signal_new (NM_CONNECTIVITY_PERIODIC_CHECK,
+ signals[CONFIG_CHANGED] =
+ g_signal_new (NM_CONNECTIVITY_CONFIG_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
diff --git a/src/nm-connectivity.h b/src/nm-connectivity.h
index 6c16982307..df9295e02b 100644
--- a/src/nm-connectivity.h
+++ b/src/nm-connectivity.h
@@ -34,7 +34,7 @@
#define NM_IS_CONNECTIVITY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONNECTIVITY))
#define NM_CONNECTIVITY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONNECTIVITY, NMConnectivityClass))
-#define NM_CONNECTIVITY_PERIODIC_CHECK "nm-connectivity-periodic-check"
+#define NM_CONNECTIVITY_CONFIG_CHANGED "config-changed"
typedef struct _NMConnectivityClass NMConnectivityClass;
@@ -46,6 +46,8 @@ const char *nm_connectivity_state_to_string (NMConnectivityState state);
gboolean nm_connectivity_check_enabled (NMConnectivity *self);
+guint nm_connectivity_get_interval (NMConnectivity *self);
+
typedef struct _NMConnectivityCheckHandle NMConnectivityCheckHandle;
typedef void (*NMConnectivityCheckCallback) (NMConnectivity *self,
diff --git a/src/nm-manager.c b/src/nm-manager.c
index e98b9fe03f..98de80782d 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -132,10 +132,8 @@ typedef struct {
NMState state;
NMConfig *config;
- NMConnectivityState connectivity_state;
-
+ NMConnectivity *concheck_mgr;
NMPolicy *policy;
-
NMHostnameManager *hostname_manager;
struct {
@@ -170,6 +168,8 @@ typedef struct {
guint devices_inited_id;
+ NMConnectivityState connectivity_state;
+
bool startup:1;
bool devices_inited:1;
@@ -334,6 +334,34 @@ static NM_CACHED_QUARK_FCN ("autoconnect-root", autoconnect_root_quark)
/*****************************************************************************/
+static void
+concheck_config_changed_cb (NMConnectivity *connectivity,
+ NMManager *self)
+{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+ NMDevice *device;
+
+ c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst)
+ nm_device_check_connectivity_update_interval (device);
+}
+
+static NMConnectivity *
+concheck_get_mgr (NMManager *self)
+{
+ NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+
+ if (G_UNLIKELY (!priv->concheck_mgr)) {
+ priv->concheck_mgr = g_object_ref (nm_connectivity_get ());
+ g_signal_connect (priv->concheck_mgr,
+ NM_CONNECTIVITY_CONFIG_CHANGED,
+ G_CALLBACK (concheck_config_changed_cb),
+ self);
+ }
+ return priv->concheck_mgr;
+}
+
+/*****************************************************************************/
+
typedef struct {
int ifindex;
guint32 aspired_metric;
@@ -5527,10 +5555,10 @@ check_connectivity_auth_done_cb (NMAuthChain *chain,
data->remaining = 0;
c_list_for_each_entry (device, &priv->devices_lst_head, devices_lst) {
- data->remaining++;
- nm_device_check_connectivity (device,
- device_connectivity_done,
- data);
+ if (nm_device_check_connectivity (device,
+ device_connectivity_done,
+ data))
+ data->remaining++;
}
if (data->remaining == 0) {
@@ -6647,7 +6675,7 @@ get_property (GObject *object, guint prop_id,
break;
case PROP_CONNECTIVITY_CHECK_ENABLED:
g_value_set_boolean (value,
- nm_connectivity_check_enabled (nm_connectivity_get ()));
+ nm_connectivity_check_enabled (concheck_get_mgr (self)));
break;
case PROP_PRIMARY_CONNECTION:
nm_dbus_utils_g_value_set_object_path (value, priv->primary_connection);
@@ -6777,6 +6805,13 @@ dispose (GObject *object)
g_clear_pointer (&priv->checkpoint_mgr, nm_checkpoint_manager_free);
+ if (priv->concheck_mgr) {
+ g_signal_handlers_disconnect_by_func (priv->concheck_mgr,
+ G_CALLBACK (concheck_config_changed_cb),
+ self);
+ g_clear_object (&priv->concheck_mgr);
+ }
+
if (priv->auth_mgr) {
g_signal_handlers_disconnect_by_func (priv->auth_mgr,
G_CALLBACK (auth_mgr_changed),