summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-08-22 10:43:22 +0200
committerThomas Haller <thaller@redhat.com>2019-08-28 16:27:00 +0200
commit29562a9751d97eb56bb5b56f3d36a96345559a5f (patch)
tree43027ed681c41ca57e440f671eae766ca09b57c5
parent86f8f5a71c52af36e8e8d73e27612d6588d828c3 (diff)
downloadNetworkManager-29562a9751d97eb56bb5b56f3d36a96345559a5f.tar.gz
device: let devices call stage1 again after being ready to proceed
I am about to change the when stage1 gets postponed, then the way to proceed it is to schedule stage1 again (instead of scheduling stage2). The reason is that stage1 handling should be reentrant and we should keep entering it until there is no more reason to postpone it. If a subclass postpones stage1 and then later progresses it by directly scheduling stage2, then only the subclass is in control over postponing stage 2. Instead, anybody should be able to delay stage2 independently. That can only work if everybody signals readyness to proceed by scheduling stage1 again.
-rw-r--r--src/devices/nm-device-ethernet.c9
-rw-r--r--src/devices/nm-device-macsec.c6
-rw-r--r--src/devices/nm-device-wireguard.c6
-rw-r--r--src/devices/team/nm-device-team.c26
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c6
-rw-r--r--src/devices/wifi/nm-device-wifi-p2p.c36
-rw-r--r--src/devices/wifi/nm-device-wifi.c6
-rw-r--r--src/devices/wwan/nm-device-modem.c52
8 files changed, 99 insertions, 48 deletions
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index b69669ca6f..360e4d1714 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -454,8 +454,10 @@ wired_secrets_cb (NMActRequest *req,
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_NO_SECRETS);
- } else
- nm_device_activate_schedule_stage1_device_prepare (device);
+ return;
+ }
+
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
static void
@@ -851,8 +853,9 @@ pppoe_reconnect_delay (gpointer user_data)
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
priv->pppoe_wait_id = 0;
+ priv->last_pppoe_time = 0;
_LOGI (LOGD_DEVICE, "PPPoE reconnect delay complete, resuming connection...");
- nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self));
+ nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self));
return G_SOURCE_REMOVE;
}
diff --git a/src/devices/nm-device-macsec.c b/src/devices/nm-device-macsec.c
index e3e3a895b2..c4911eca28 100644
--- a/src/devices/nm-device-macsec.c
+++ b/src/devices/nm-device-macsec.c
@@ -308,8 +308,10 @@ macsec_secrets_cb (NMActRequest *req,
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_NO_SECRETS);
- } else
- nm_device_activate_schedule_stage1_device_prepare (device);
+ return;
+ }
+
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
static void
diff --git a/src/devices/nm-device-wireguard.c b/src/devices/nm-device-wireguard.c
index 572389b114..e64f33b560 100644
--- a/src/devices/nm-device-wireguard.c
+++ b/src/devices/nm-device-wireguard.c
@@ -1276,8 +1276,10 @@ _secrets_cb (NMActRequest *req,
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_NO_SECRETS);
- } else
- nm_device_activate_schedule_stage1_device_prepare (device);
+ return;
+ }
+
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
static void
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index c02c308bd8..bea756be35 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -56,6 +56,7 @@ typedef struct {
guint teamd_read_timeout;
guint teamd_dbus_watch;
bool kill_in_progress:1;
+ NMDeviceStageState stage1_state:3;
} NMDeviceTeamPrivate;
struct _NMDeviceTeam {
@@ -407,19 +408,20 @@ teamd_dbus_appeared (GDBusConnection *connection,
*/
success = ensure_teamd_connection (device);
- if (nm_device_get_state (device) != NM_DEVICE_STATE_PREPARE)
+ if ( nm_device_get_state (device) != NM_DEVICE_STATE_PREPARE
+ || priv->stage1_state != NM_DEVICE_STAGE_STATE_PENDING)
return;
+ if (success)
+ success = teamd_read_config (self);
+
if (!success) {
- if (!nm_device_sys_iface_state_is_external_or_assume (device)) {
- teamd_cleanup (self, TRUE);
- nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
- }
+ nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
return;
}
- if (teamd_read_config (self))
- nm_device_activate_schedule_stage2_device_config (device);
+ priv->stage1_state = NM_DEVICE_STAGE_STATE_COMPLETED;
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
static void
@@ -658,6 +660,14 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
if (!s_team)
g_return_val_if_reached (NM_ACT_STAGE_RETURN_FAILURE);
+ if (priv->stage1_state == NM_DEVICE_STAGE_STATE_PENDING)
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+
+ if (priv->stage1_state == NM_DEVICE_STAGE_STATE_COMPLETED)
+ return NM_ACT_STAGE_RETURN_SUCCESS;
+
+ priv->stage1_state = NM_DEVICE_STAGE_STATE_PENDING;
+
if (priv->tdc) {
/* If the existing teamd config is the same as we're about to use,
* then we can proceed. If it's not the same, and we have a PID,
@@ -701,6 +711,8 @@ deactivate (NMDevice *device)
NMDeviceTeam *self = NM_DEVICE_TEAM (device);
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self);
+ priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT;
+
if (nm_device_sys_iface_state_is_external (device))
return;
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index 0a89e5a671..3551a9e486 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -58,7 +58,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceOlpcMesh,
typedef struct {
NMDevice *companion;
NMManager *manager;
- gboolean stage1_waiting;
+ bool stage1_waiting:1;
} NMDeviceOlpcMeshPrivate;
struct _NMDeviceOlpcMesh {
@@ -166,6 +166,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
return NM_ACT_STAGE_RETURN_POSTPONE;
}
+ priv->stage1_waiting = FALSE;
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@@ -249,10 +250,9 @@ companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_d
return;
g_object_get (companion, NM_DEVICE_WIFI_SCANNING, &scanning, NULL);
-
if (!scanning) {
priv->stage1_waiting = FALSE;
- nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self));
+ nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self));
}
}
diff --git a/src/devices/wifi/nm-device-wifi-p2p.c b/src/devices/wifi/nm-device-wifi-p2p.c
index fe2f7bc4d8..5e75e26022 100644
--- a/src/devices/wifi/nm-device-wifi-p2p.c
+++ b/src/devices/wifi/nm-device-wifi-p2p.c
@@ -63,6 +63,7 @@ typedef struct {
CList peers_lst_head;
+ guint find_peer_timeout_id;
guint sup_timeout_id;
guint peer_dump_id;
guint peer_missing_id;
@@ -349,7 +350,7 @@ supplicant_find_timeout_cb (gpointer user_data)
NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (user_data);
NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self);
- priv->sup_timeout_id = 0;
+ priv->find_peer_timeout_id = 0;
nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface);
@@ -386,10 +387,10 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection);
if (!peer) {
/* Set up a timeout on the find attempt and run a find for the same period of time */
- if (priv->sup_timeout_id == 0) {
- priv->sup_timeout_id = g_timeout_add_seconds (10,
- supplicant_find_timeout_cb,
- self);
+ if (priv->find_peer_timeout_id == 0) {
+ priv->find_peer_timeout_id = g_timeout_add_seconds (10,
+ supplicant_find_timeout_cb,
+ self);
nm_supplicant_interface_p2p_start_find (priv->mgmt_iface, 10);
}
@@ -436,7 +437,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
NMWifiP2PPeer *peer;
GBytes *wfd_ies;
- nm_clear_g_source (&priv->sup_timeout_id);
+ if (nm_clear_g_source (&priv->find_peer_timeout_id))
+ nm_assert_not_reached ();
if (!priv->mgmt_iface) {
NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
@@ -468,9 +470,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
"pbc", NULL);
/* Set up a timeout on the connect attempt */
- priv->sup_timeout_id = g_timeout_add_seconds (45,
- supplicant_connection_timeout_cb,
- self);
+ if (priv->sup_timeout_id == 0) {
+ priv->sup_timeout_id = g_timeout_add_seconds (45,
+ supplicant_connection_timeout_cb,
+ self);
+ }
/* We'll get stage3 started when the P2P group has been started */
return NM_ACT_STAGE_RETURN_POSTPONE;
@@ -525,17 +529,19 @@ peer_add_remove (NMDeviceWifiP2P *self,
if (is_adding) {
/* If we are in prepare state, then we are currently runnign a find
* to search for the requested peer. */
- if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) {
+ if (priv->find_peer_timeout_id != 0) {
NMConnection *connection;
+ nm_assert (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE);
+
connection = nm_device_get_applied_connection (device);
- g_assert (connection);
+ nm_assert (NM_IS_CONNECTION (connection));
peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection);
if (peer) {
/* A peer for the connection was found, cancel the timeout and go to configure state. */
- nm_clear_g_source (&priv->sup_timeout_id);
- nm_device_activate_schedule_stage2_device_config (device);
+ nm_clear_g_source (&priv->find_peer_timeout_id);
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
}
@@ -594,9 +600,10 @@ static void
deactivate (NMDevice *device)
{
NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (device);
- NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self);
int ifindex = nm_device_get_ip_ifindex (device);
+ NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self);
+ nm_clear_g_source (&priv->find_peer_timeout_id);
nm_clear_g_source (&priv->sup_timeout_id);
nm_clear_g_source (&priv->peer_missing_id);
@@ -902,6 +909,7 @@ supplicant_interfaces_release (NMDeviceWifiP2P *self, gboolean set_is_waiting)
nm_supplicant_manager_set_wfd_ies (priv->sup_mgr, NULL);
g_signal_handlers_disconnect_by_data (priv->mgmt_iface, self);
g_clear_object (&priv->mgmt_iface);
+ nm_clear_g_source (&priv->find_peer_timeout_id);
nm_clear_g_source (&priv->sup_timeout_id);
}
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index d9394ffdd5..28e8bbefb6 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -1735,8 +1735,10 @@ wifi_secrets_cb (NMActRequest *req,
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_NO_SECRETS);
- } else
- nm_device_activate_schedule_stage1_device_prepare (device);
+ return;
+ }
+
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
static void
diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c
index be0993916d..7ba664394a 100644
--- a/src/devices/wwan/nm-device-modem.c
+++ b/src/devices/wwan/nm-device-modem.c
@@ -48,10 +48,11 @@ typedef struct {
NMModem *modem;
NMDeviceModemCapabilities caps;
NMDeviceModemCapabilities current_caps;
- gboolean rf_enabled;
char *device_id;
char *operator_code;
char *apn;
+ bool rf_enabled:1;
+ NMDeviceStageState stage1_state:3;
} NMDeviceModemPrivate;
struct _NMDeviceModem {
@@ -119,16 +120,17 @@ modem_prepare_result (NMModem *modem,
gpointer user_data)
{
NMDeviceModem *self = NM_DEVICE_MODEM (user_data);
+ NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
NMDevice *device = NM_DEVICE (self);
- NMDeviceState state;
NMDeviceStateReason reason = i_reason;
- state = nm_device_get_state (device);
- g_return_if_fail (state == NM_DEVICE_STATE_PREPARE);
+ if ( nm_device_get_state (device) != NM_DEVICE_STATE_PREPARE
+ || priv->stage1_state != NM_DEVICE_STAGE_STATE_PENDING) {
+ nm_assert_not_reached ();
+ success = FALSE;
+ }
- if (success)
- nm_device_activate_schedule_stage2_device_config (device);
- else {
+ if (!success) {
/* There are several reasons to block autoconnection at device level:
*
* - Wrong SIM-PIN: The device won't autoconnect because it doesn't make sense
@@ -164,7 +166,11 @@ modem_prepare_result (NMModem *modem,
break;
}
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, reason);
+ return;
}
+
+ priv->stage1_state = NM_DEVICE_STAGE_STATE_COMPLETED;
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
static void
@@ -187,16 +193,19 @@ static void
modem_auth_result (NMModem *modem, GError *error, gpointer user_data)
{
NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
+
+ g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
if (error) {
nm_device_state_changed (device,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_NO_SECRETS);
- } else {
- /* Otherwise, on success for modem secrets we need to schedule stage1 again */
- g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH);
- nm_device_activate_schedule_stage1_device_prepare (device);
+ return;
}
+
+ priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT;
+ nm_device_activate_schedule_stage1_device_prepare (device);
}
static void
@@ -542,7 +551,10 @@ complete_connection (NMDevice *device,
static void
deactivate (NMDevice *device)
{
- nm_modem_deactivate (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device);
+ NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
+
+ nm_modem_deactivate (priv->modem, device);
+ priv->stage1_state = NM_DEVICE_STAGE_STATE_INIT;
}
/*****************************************************************************/
@@ -583,14 +595,24 @@ deactivate_async (NMDevice *self,
static NMActStageReturn
act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
+ NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
NMActRequest *req;
req = nm_device_get_act_request (device);
g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE);
- return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem,
- req,
- out_failure_reason);
+ if (priv->stage1_state == NM_DEVICE_STAGE_STATE_INIT) {
+ priv->stage1_state = NM_DEVICE_STAGE_STATE_PENDING;
+ return nm_modem_act_stage1_prepare (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem,
+ req,
+ out_failure_reason);
+ }
+
+ if (priv->stage1_state == NM_DEVICE_STAGE_STATE_PENDING)
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+
+ nm_assert (priv->stage1_state == NM_DEVICE_STAGE_STATE_COMPLETED);
+ return NM_ACT_STAGE_RETURN_SUCCESS;
}
static NMActStageReturn