diff options
-rw-r--r-- | src/devices/nm-device.c | 344 | ||||
-rw-r--r-- | src/devices/nm-device.h | 2 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/nm-connectivity.c | 33 | ||||
-rw-r--r-- | src/nm-connectivity.h | 4 | ||||
-rw-r--r-- | src/nm-manager.c | 51 |
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), |