summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-04-20 11:04:07 +0200
committerThomas Haller <thaller@redhat.com>2018-04-20 12:07:20 +0200
commit5c4e67ba3df163add5b559d745b9811d48e8f8db (patch)
tree14dfd549cef868fb5dc2017d0ec95ec8e92ebbd7
parent019aebacc1b118494c579027d323790f2b48e266 (diff)
downloadNetworkManager-5c4e67ba3df163add5b559d745b9811d48e8f8db.tar.gz
device/connectivity: fix handling of completed periodic checks in concheck_cb()
-rw-r--r--src/devices/nm-device.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 1ab4eec7e2..a90240fa62 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -2428,7 +2428,7 @@ nm_device_check_connectivity_update_interval (NMDevice *self)
}
static void
-concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_periodic)
+concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean allow_periodic_bump)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
@@ -2465,8 +2465,7 @@ concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_pe
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)
+ if (allow_periodic_bump)
concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_BUMP);
return;
}
@@ -2482,8 +2481,7 @@ concheck_update_state (NMDevice *self, NMConnectivityState state, gboolean is_pe
* the timeout interval to the min. */
concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_MIN);
} else {
- if ( is_periodic
- && priv->concheck_p_cur_id)
+ if (allow_periodic_bump)
concheck_periodic_schedule_set (self, CONCHECK_SCHEDULE_RETURNED_BUMP);
}
@@ -2542,6 +2540,9 @@ concheck_cb (NMConnectivity *connectivity,
NMDeviceConnectivityHandle *handle;
NMDeviceConnectivityHandle *other_handle;
gboolean handle_is_alive;
+ gboolean allow_periodic_bump;
+ gboolean any_periodic_before;
+ gboolean any_periodic_after;
guint64 seq;
handle = user_data;
@@ -2577,8 +2578,35 @@ concheck_cb (NMConnectivity *connectivity,
seq = handle->seq;
+ /* find out, if there are any periodic checks pending (either whether they
+ * were scheduled before or after @handle. */
+ any_periodic_before = FALSE;
+ any_periodic_after = FALSE;
+ c_list_for_each_entry (other_handle, &priv->concheck_lst_head, concheck_lst) {
+ if (other_handle->is_periodic) {
+ if (other_handle->seq < seq)
+ any_periodic_before = TRUE;
+ else if (other_handle->seq > seq)
+ any_periodic_after = TRUE;
+ }
+ }
+ if (NM_IN_SET (state, NM_CONNECTIVITY_ERROR)) {
+ /* the request failed. We consider this periodic check only as completed if
+ * this was a periodic check, and there are not checks pending (either
+ * before or after this one).
+ *
+ * We allow_periodic_bump, if the request failed and there are
+ * still other requests periodic pending. */
+ allow_periodic_bump = handle->is_periodic && !any_periodic_before && !any_periodic_after;
+ } else {
+ /* the request succeeded. This marks the completion of a periodic check,
+ * if this handle was periodic, or any previously scheduled one (that
+ * we are going to complete below). */
+ allow_periodic_bump = handle->is_periodic || any_periodic_before;
+ }
+
/* first update the new state, and emit signals. */
- concheck_update_state (self, state, handle->is_periodic);
+ concheck_update_state (self, state, allow_periodic_bump);
handle_is_alive = FALSE;
@@ -2683,6 +2711,10 @@ nm_device_check_connectivity_cancel (NMDeviceConnectivityHandle *handle)
g_return_if_fail (NM_IS_DEVICE (handle->self));
g_return_if_fail (!c_list_is_empty (&handle->concheck_lst));
+ /* nobody has access to periodic handles, and cannot cancel
+ * them externally. */
+ nm_assert (!handle->is_periodic);
+
nm_utils_error_set_cancelled (&cancelled_error, FALSE, "NMDevice");
concheck_handle_complete (handle, cancelled_error);
}