summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2013-09-11 09:21:17 -0500
committerDan Williams <dcbw@redhat.com>2013-10-31 14:15:08 -0500
commit1768b3abd5581f1fee9a4937f34f26f5b23a1a70 (patch)
tree3cbfe7b093b26552d523139e79c5ddeb00006a77
parentf95bca2dcf6315ca116e545373ecce6bd360e424 (diff)
downloadNetworkManager-1768b3abd5581f1fee9a4937f34f26f5b23a1a70.tar.gz
core: add slave to master in stage1_prepare, not nm_device_activate()
When ActiveConnections take over authentication, it may mean that the master active connection is still handling authentication when the slave starts to activate. Thus the master device may still be in DISCONNECTED state and not ready to enslave the slave.
-rw-r--r--src/devices/nm-device.c77
1 files changed, 59 insertions, 18 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 5c87525b44..660e26a59d 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -288,6 +288,7 @@ typedef struct {
/* master interface for bridge/bond/team slave */
NMDevice * master;
gboolean enslaved;
+ guint master_ready_id;
/* slave management */
gboolean is_master;
@@ -1935,10 +1936,61 @@ nm_device_ip_config_should_fail (NMDevice *self, gboolean ip6)
return FALSE;
}
+static void
+master_ready_cb (NMActiveConnection *active,
+ GParamSpec *pspec,
+ NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ NMActiveConnection *master;
+
+ g_assert (priv->state == NM_DEVICE_STATE_PREPARE);
+
+ /* Notify a master device that it has a new slave */
+ g_assert (nm_active_connection_get_master_ready (active));
+ master = nm_active_connection_get_master (active);
+
+ priv->master = g_object_ref (nm_active_connection_get_device (master));
+ nm_device_master_add_slave (priv->master, self);
+
+ nm_log_dbg (LOGD_DEVICE, "(%s): master connection ready; master device %s",
+ nm_device_get_iface (self),
+ nm_device_get_iface (priv->master));
+
+ if (priv->master_ready_id) {
+ g_signal_handler_disconnect (active, priv->master_ready_id);
+ priv->master_ready_id = 0;
+ }
+
+ nm_device_activate_schedule_stage2_device_config (self);
+}
+
static NMActStageReturn
act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason)
{
- return NM_ACT_STAGE_RETURN_SUCCESS;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS;
+ NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request);
+
+ if (nm_active_connection_get_master (active)) {
+ /* If the master connection is ready for slaves, attach ourselves */
+ if (nm_active_connection_get_master_ready (active))
+ master_ready_cb (active, NULL, self);
+ else {
+ nm_log_dbg (LOGD_DEVICE, "(%s): waiting for master connection to become ready",
+ nm_device_get_iface (self));
+
+ /* Attach a signal handler and wait for the master connection to begin activating */
+ g_assert (priv->master_ready_id == 0);
+ priv->master_ready_id = g_signal_connect (active,
+ "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY,
+ (GCallback) master_ready_cb,
+ self);
+ ret = NM_ACT_STAGE_RETURN_POSTPONE;
+ }
+ }
+
+ return ret;
}
/*
@@ -4024,6 +4076,11 @@ clear_act_request (NMDevice *self)
nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE);
+ if (priv->master_ready_id) {
+ g_signal_handler_disconnect (priv->act_request, priv->master_ready_id);
+ priv->master_ready_id = 0;
+ }
+
g_object_unref (priv->act_request);
priv->act_request = NULL;
}
@@ -4427,9 +4484,6 @@ nm_device_activate (NMDevice *self, NMActRequest *req)
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
nm_device_activate_schedule_stage3_ip_config_start (self);
} else {
- NMActiveConnection *master;
- NMDevice *master_device;
-
/* HACK: update the state a bit early to avoid a race between the
* scheduled stage1 handler and nm_policy_device_change_check() thinking
* that the activation request isn't deferred because the deferred bit
@@ -4437,20 +4491,6 @@ nm_device_activate (NMDevice *self, NMActRequest *req)
*/
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
- /* Handle any dependencies this connection might have */
- master = nm_active_connection_get_master (NM_ACTIVE_CONNECTION (req));
- if (master) {
- master_device = nm_active_connection_get_device (master);
- if (master_device) {
- /* Master should at least already be activating */
- g_assert (nm_device_get_state (master_device) > NM_DEVICE_STATE_DISCONNECTED);
-
- g_assert (priv->master == NULL);
- priv->master = g_object_ref (master_device);
- nm_device_master_add_slave (master_device, self);
- }
- }
-
nm_device_activate_schedule_stage1_device_prepare (self);
}
}
@@ -5033,6 +5073,7 @@ dispose (GObject *object)
dnsmasq_cleanup (self);
g_warn_if_fail (priv->slaves == NULL);
+ g_assert (priv->master_ready_id == 0);
/* Take the device itself down and clear its IPv4 configuration */
if (nm_device_get_managed (self) && deconfigure) {