connectivity: merge branch 'th/fix-fake-connectivity-state'

https://github.com/NetworkManager/NetworkManager/pull/89
This commit is contained in:
Thomas Haller 2018-04-12 08:23:29 +02:00
commit 3b5a522ef6
4 changed files with 63 additions and 40 deletions

View file

@ -180,6 +180,7 @@ enum {
REMOVED, REMOVED,
RECHECK_AUTO_ACTIVATE, RECHECK_AUTO_ACTIVATE,
RECHECK_ASSUME, RECHECK_ASSUME,
CONNECTIVITY_CHANGED,
LAST_SIGNAL, LAST_SIGNAL,
}; };
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
@ -631,6 +632,8 @@ static void _set_mtu (NMDevice *self, guint32 mtu);
static void _commit_mtu (NMDevice *self, const NMIP4Config *config); static void _commit_mtu (NMDevice *self, const NMIP4Config *config);
static void _cancel_activation (NMDevice *self); static void _cancel_activation (NMDevice *self);
static void concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_periodic);
/*****************************************************************************/ /*****************************************************************************/
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (queued_state_to_string, NMDeviceState, NM_UTILS_LOOKUP_STR_DEFINE_STATIC (queued_state_to_string, NMDeviceState,
@ -2389,6 +2392,9 @@ nm_device_check_connectivity_update_interval (NMDevice *self)
if (!new_interval) { if (!new_interval) {
/* this will cancel any potentially pending timeout. */ /* this will cancel any potentially pending timeout. */
concheck_periodic_schedule_do (self, 0); concheck_periodic_schedule_do (self, 0);
/* also update the fake connectivity state. */
concheck_update_state (self, NM_CONNECTIVITY_FAKE, TRUE);
return; return;
} }
@ -2418,6 +2424,10 @@ concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_pe
/* If the connectivity check is disabled and we obtain a fake /* If the connectivity check is disabled and we obtain a fake
* result, make an optimistic guess. */ * result, make an optimistic guess. */
if (priv->state == NM_DEVICE_STATE_ACTIVATED) { if (priv->state == NM_DEVICE_STATE_ACTIVATED) {
/* FIXME: the fake connectivity state depends on the availablility of
* a default route. However, we have no mechanism that rechecks the
* value if a device route appears/disappears after the device
* was activated. */
if (nm_device_get_best_default_route (self, AF_UNSPEC)) if (nm_device_get_best_default_route (self, AF_UNSPEC))
state = NM_CONNECTIVITY_FULL; state = NM_CONNECTIVITY_FULL;
else else
@ -2457,6 +2467,7 @@ concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_pe
priv->connectivity_state = state; priv->connectivity_state = state;
_notify (self, PROP_CONNECTIVITY); _notify (self, PROP_CONNECTIVITY);
g_signal_emit (self, signals[CONNECTIVITY_CHANGED], 0);
if ( priv->state == NM_DEVICE_STATE_ACTIVATED if ( priv->state == NM_DEVICE_STATE_ACTIVATED
&& !nm_device_sys_iface_state_is_external (self)) { && !nm_device_sys_iface_state_is_external (self)) {
@ -2499,7 +2510,8 @@ concheck_cb (NMConnectivity *connectivity,
GError *error, GError *error,
gpointer user_data) gpointer user_data)
{ {
gs_unref_object NMDevice *self = NULL; _nm_unused gs_unref_object NMDevice *self_keep_alive = NULL;
NMDevice *self;
NMDevicePrivate *priv; NMDevicePrivate *priv;
NMDeviceConnectivityHandle *handle; NMDeviceConnectivityHandle *handle;
NMDeviceConnectivityHandle *other_handle; NMDeviceConnectivityHandle *other_handle;
@ -2511,20 +2523,24 @@ concheck_cb (NMConnectivity *connectivity,
nm_assert (NM_IS_DEVICE (handle->self)); nm_assert (NM_IS_DEVICE (handle->self));
handle->c_handle = NULL; handle->c_handle = NULL;
self = g_object_ref (handle->self); self = 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)) { if (nm_utils_error_is_cancelled (error, FALSE)) {
/* the only place where we nm_connectivity_check_cancel(@c_handle), is /* the only place where we nm_connectivity_check_cancel(@c_handle), is
* from inside concheck_handle_event(). This is a recursive call, * from inside concheck_handle_event(). This is a recursive call,
* nothing to do. */ * nothing to do. */
_LOGT (LOGD_CONCHECK, "connectivity: complete check (seq:%llu, obsoleted by later request returning)",
(long long unsigned) handle->seq);
return; return;
} }
self_keep_alive = g_object_ref (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, "", ""));
/* we keep NMConnectivity instance alive. It cannot be disposing. */ /* we keep NMConnectivity instance alive. It cannot be disposing. */
nm_assert (!nm_utils_error_is_cancelled (error, TRUE)); nm_assert (!nm_utils_error_is_cancelled (error, TRUE));
@ -15739,4 +15755,12 @@ nm_device_class_init (NMDeviceClass *klass)
G_SIGNAL_RUN_FIRST, G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL, 0, NULL, NULL, NULL,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
signals[CONNECTIVITY_CHANGED] =
g_signal_new (NM_DEVICE_CONNECTIVITY_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
} }

View file

@ -135,6 +135,7 @@ nm_device_state_reason_check (NMDeviceStateReason reason)
#define NM_DEVICE_STATE_CHANGED "state-changed" #define NM_DEVICE_STATE_CHANGED "state-changed"
#define NM_DEVICE_LINK_INITIALIZED "link-initialized" #define NM_DEVICE_LINK_INITIALIZED "link-initialized"
#define NM_DEVICE_AUTOCONNECT_ALLOWED "autoconnect-allowed" #define NM_DEVICE_AUTOCONNECT_ALLOWED "autoconnect-allowed"
#define NM_DEVICE_CONNECTIVITY_CHANGED "connectivity-changed"
#define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms" #define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms"
#define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes" #define NM_DEVICE_STATISTICS_TX_BYTES "tx-bytes"

View file

@ -631,9 +631,7 @@ _dispatcher_call (NMDispatcherAction action,
if (!device_dhcp6_props) if (!device_dhcp6_props)
device_dhcp6_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0)); device_dhcp6_props = g_variant_ref_sink (g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0));
#if WITH_CONCHECK
connectivity_state_string = nm_connectivity_state_to_string (connectivity_state); connectivity_state_string = nm_connectivity_state_to_string (connectivity_state);
#endif
/* Send the action to the dispatcher */ /* Send the action to the dispatcher */
if (blocking) { if (blocking) {

View file

@ -1142,26 +1142,6 @@ _nm_state_to_string (NMState state)
} }
} }
static void
set_state (NMManager *self, NMState state)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
if (priv->state == state)
return;
priv->state = state;
_LOGI (LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string (state));
_notify (self, PROP_STATE);
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
&interface_info_manager,
&signal_info_state_changed,
"(u)",
(guint32) priv->state);
}
static NMState static NMState
find_best_device_state (NMManager *manager) find_best_device_state (NMManager *manager)
{ {
@ -1232,26 +1212,38 @@ nm_manager_update_metered (NMManager *self)
} }
static void static void
nm_manager_update_state (NMManager *manager) nm_manager_update_state (NMManager *self)
{ {
NMManagerPrivate *priv; NMManagerPrivate *priv;
NMState new_state = NM_STATE_DISCONNECTED; NMState new_state = NM_STATE_DISCONNECTED;
g_return_if_fail (NM_IS_MANAGER (manager)); g_return_if_fail (NM_IS_MANAGER (self));
priv = NM_MANAGER_GET_PRIVATE (manager); priv = NM_MANAGER_GET_PRIVATE (self);
if (manager_sleeping (manager)) if (manager_sleeping (self))
new_state = NM_STATE_ASLEEP; new_state = NM_STATE_ASLEEP;
else else
new_state = find_best_device_state (manager); new_state = find_best_device_state (self);
if ( new_state >= NM_STATE_CONNECTED_LOCAL if ( new_state >= NM_STATE_CONNECTED_LOCAL
&& priv->connectivity_state == NM_CONNECTIVITY_FULL) { && priv->connectivity_state == NM_CONNECTIVITY_FULL) {
new_state = NM_STATE_CONNECTED_GLOBAL; new_state = NM_STATE_CONNECTED_GLOBAL;
} }
set_state (manager, new_state); if (priv->state == new_state)
return;
priv->state = new_state;
_LOGI (LOGD_CORE, "NetworkManager state is now %s", _nm_state_to_string (new_state));
_notify (self, PROP_STATE);
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
&interface_info_manager,
&signal_info_state_changed,
"(u)",
(guint32) priv->state);
} }
static void static void
@ -2512,7 +2504,6 @@ device_realized (NMDevice *device,
static void static void
device_connectivity_changed (NMDevice *device, device_connectivity_changed (NMDevice *device,
GParamSpec *pspec,
NMManager *self) NMManager *self)
{ {
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
@ -2520,11 +2511,20 @@ device_connectivity_changed (NMDevice *device,
NMConnectivityState state; NMConnectivityState state;
NMDevice *dev; NMDevice *dev;
c_list_for_each_entry (dev, &priv->devices_lst_head, devices_lst) { best_state = nm_device_get_connectivity_state (device);
state = nm_device_get_connectivity_state (dev); if (best_state < NM_CONNECTIVITY_FULL) {
if (state > best_state) c_list_for_each_entry (dev, &priv->devices_lst_head, devices_lst) {
state = nm_device_get_connectivity_state (dev);
if (state <= best_state)
continue;
best_state = state; best_state = state;
if (best_state >= NM_CONNECTIVITY_FULL) {
/* it doesn't get better than this. */
break;
}
}
} }
nm_assert (best_state <= NM_CONNECTIVITY_FULL);
if (best_state != priv->connectivity_state) { if (best_state != priv->connectivity_state) {
priv->connectivity_state = best_state; priv->connectivity_state = best_state;
@ -2646,7 +2646,7 @@ add_device (NMManager *self, NMDevice *device, GError **error)
G_CALLBACK (device_realized), G_CALLBACK (device_realized),
self); self);
g_signal_connect (device, "notify::" NM_DEVICE_CONNECTIVITY, g_signal_connect (device, NM_DEVICE_CONNECTIVITY_CHANGED,
G_CALLBACK (device_connectivity_changed), G_CALLBACK (device_connectivity_changed),
self); self);