core: implement connection assumption

Mark activation requests that contain connections to be assumed,
and use that to short-circuit various parts of the activation
process by not touching various device attributes, since they
are already set up.  Also ensure the device is not deactivated
when it initially becomes managed, because that would kill the
connection we are about to assume.
This commit is contained in:
Dan Williams
2009-08-05 18:03:09 -04:00
parent 4802094985
commit 78bb1c01b7
6 changed files with 132 additions and 34 deletions

View File

@@ -140,8 +140,14 @@ static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReas
static gboolean nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware);
static gboolean nm_device_is_up (NMDevice *self);
static gboolean nm_device_set_ip4_config (NMDevice *dev, NMIP4Config *config, NMDeviceStateReason *reason);
static gboolean nm_device_set_ip6_config (NMDevice *dev, NMIP6Config *config, NMDeviceStateReason *reason);
static gboolean nm_device_set_ip4_config (NMDevice *dev,
NMIP4Config *config,
gboolean assumed,
NMDeviceStateReason *reason);
static gboolean nm_device_set_ip6_config (NMDevice *dev,
NMIP6Config *config,
gboolean assumed,
NMDeviceStateReason *reason);
static void
device_interface_init (NMDeviceInterface *device_interface_class)
@@ -774,7 +780,7 @@ handle_autoip_change (NMDevice *self, NMDeviceStateReason *reason)
g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP4_CONFIG, config);
if (!nm_device_set_ip4_config (self, config, reason)) {
if (!nm_device_set_ip4_config (self, config, FALSE, reason)) {
nm_warning ("(%s): failed to update IP4 config in response to autoip event.",
nm_device_get_iface (self));
return FALSE;
@@ -1724,19 +1730,20 @@ static gboolean
nm_device_activate_stage5_ip_config_commit (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMIP4Config *ip4_config = NULL;
NMIP6Config *ip6_config = NULL;
const char *iface, *method = NULL;
NMConnection *connection;
NMSettingIP4Config *s_ip4;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
gboolean assumed;
ip4_config = g_object_get_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP4_CONFIG);
g_assert (ip4_config);
ip6_config = g_object_get_data (G_OBJECT (nm_device_get_act_request (self)),
NM_ACT_REQUEST_IP6_CONFIG);
/* FIXME g_assert (ip6_config); */
/* Clear the activation source ID now that this stage has run */
activation_source_clear (self, FALSE, 0);
@@ -1745,12 +1752,14 @@ nm_device_activate_stage5_ip_config_commit (gpointer user_data)
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) started...",
iface);
if (!nm_device_set_ip4_config (self, ip4_config, &reason)) {
assumed = nm_act_request_get_assumed (priv->act_request);
if (!nm_device_set_ip4_config (self, ip4_config, assumed, &reason)) {
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
goto out;
}
if (!nm_device_set_ip6_config (self, ip6_config, &reason)) {
if (ip6_config && !nm_device_set_ip6_config (self, ip6_config, assumed, &reason)) {
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) IPv6 failed",
iface);
}
@@ -1776,7 +1785,8 @@ out:
/* Balance IP config creation; device takes ownership in set_ip*_config() */
g_object_unref (ip4_config);
g_object_unref (ip6_config);
if (ip6_config)
g_object_unref (ip6_config);
return FALSE;
}
@@ -1920,8 +1930,8 @@ nm_device_deactivate (NMDeviceInterface *device, NMDeviceStateReason reason)
nm_device_deactivate_quickly (self);
/* Clean up nameservers and addresses */
nm_device_set_ip4_config (self, NULL, &ignored);
nm_device_set_ip6_config (self, NULL, &ignored);
nm_device_set_ip4_config (self, NULL, FALSE, &ignored);
nm_device_set_ip6_config (self, NULL, FALSE, &ignored);
/* Take out any entries in the routing table and any IP address the device had. */
nm_system_device_flush_routes (self);
@@ -2022,13 +2032,22 @@ nm_device_activate (NMDeviceInterface *device,
G_CALLBACK (connection_secrets_failed_cb),
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
* gets cleared a bit too early, when the connection becomes valid.
*/
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
nm_device_activate_schedule_stage1_device_prepare (self);
if (!nm_act_request_get_assumed (req)) {
/* 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
* gets cleared a bit too early, when the connection becomes valid.
*/
nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE);
nm_device_activate_schedule_stage1_device_prepare (self);
} else {
/* If it's an assumed connection, let the device subclass short-circuit
* the normal connection process and just copy its IP configs from the
* interface.
*/
nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE);
nm_device_activate_schedule_stage3_ip_config_start (self);
}
return TRUE;
}
@@ -2093,6 +2112,7 @@ handle_dhcp_lease_change (NMDevice *device)
NMActRequest *req;
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
const char *ip_iface;
gboolean assumed;
if (!nm_device_get_use_dhcp (device)) {
nm_warning ("got DHCP rebind for device that wasn't using DHCP.");
@@ -2118,7 +2138,8 @@ handle_dhcp_lease_change (NMDevice *device)
g_object_set_data (G_OBJECT (req), NM_ACT_REQUEST_IP4_CONFIG, config);
if (nm_device_set_ip4_config (device, config, &reason)) {
assumed = nm_act_request_get_assumed (req);
if (nm_device_set_ip4_config (device, config, assumed, &reason)) {
nm_dhcp4_config_reset (priv->dhcp4_config);
nm_dhcp_manager_foreach_dhcp4_option (priv->dhcp_manager,
ip_iface,
@@ -2276,6 +2297,7 @@ nm_device_get_ip4_config (NMDevice *self)
static gboolean
nm_device_set_ip4_config (NMDevice *self,
NMIP4Config *new_config,
gboolean assumed,
NMDeviceStateReason *reason)
{
NMDevicePrivate *priv;
@@ -2311,8 +2333,13 @@ nm_device_set_ip4_config (NMDevice *self,
if (new_config) {
priv->ip4_config = g_object_ref (new_config);
success = nm_system_apply_ip4_config (ip_iface, new_config, nm_device_get_priority (self), diff);
if (success) {
/* Don't touch the device's actual IP config if the connection is
* assumed when NM starts.
*/
if (!assumed)
success = nm_system_apply_ip4_config (ip_iface, new_config, nm_device_get_priority (self), diff);
if (success || assumed) {
/* Export over D-Bus */
if (!nm_ip4_config_get_dbus_path (new_config))
nm_ip4_config_export (new_config);
@@ -2373,6 +2400,7 @@ nm_device_update_ip4_address (NMDevice *self)
static gboolean
nm_device_set_ip6_config (NMDevice *self,
NMIP6Config *new_config,
gboolean assumed,
NMDeviceStateReason *reason)
{
NMDevicePrivate *priv;
@@ -2408,8 +2436,13 @@ nm_device_set_ip6_config (NMDevice *self,
if (new_config) {
priv->ip6_config = g_object_ref (new_config);
success = nm_system_apply_ip6_config (ip_iface, new_config, nm_device_get_priority (self), diff);
if (success) {
/* Don't touch the device's actual IP config if the connection is
* assumed when NM starts.
*/
if (!assumed)
success = nm_system_apply_ip6_config (ip_iface, new_config, nm_device_get_priority (self), diff);
if (success || assumed) {
/* Export over D-Bus */
if (!nm_ip6_config_get_dbus_path (new_config))
nm_ip6_config_export (new_config);
@@ -2587,7 +2620,7 @@ dispose (GObject *object)
NMDeviceStateReason ignored = NM_DEVICE_STATE_REASON_NONE;
nm_device_take_down (self, FALSE, NM_DEVICE_STATE_REASON_REMOVED);
nm_device_set_ip4_config (self, NULL, &ignored);
nm_device_set_ip4_config (self, NULL, FALSE, &ignored);
}
clear_act_request (self);
@@ -2880,8 +2913,14 @@ nm_device_state_changed (NMDevice *device,
if (!nm_device_bring_up (device, TRUE, &no_firmware) && no_firmware)
nm_warning ("%s: firmware may be missing.", nm_device_get_iface (device));
}
/* Fall through, so when the device needs to be deactivated due to
* eg carrier changes we actually deactivate it */
/* Ensure the device gets deactivated in response to stuff like
* carrier changes or rfkill. But don't deactivate devices that are
* about to assume a connection since that defeats the purpose of
* assuming the device's existing connection.
*/
if (reason != NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED)
nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device), reason);
break;
case NM_DEVICE_STATE_DISCONNECTED:
if (old_state != NM_DEVICE_STATE_UNAVAILABLE)
nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device), reason);