mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-04 04:00:17 +01:00
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:
parent
4802094985
commit
78bb1c01b7
6 changed files with 132 additions and 34 deletions
|
|
@ -357,6 +357,9 @@ typedef enum {
|
|||
/* Carrier/link changed */
|
||||
NM_DEVICE_STATE_REASON_CARRIER,
|
||||
|
||||
/* The device's existing connection was assumed */
|
||||
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,
|
||||
|
||||
/* Unused */
|
||||
NM_DEVICE_STATE_REASON_LAST = 0xFFFF
|
||||
} NMDeviceStateReason;
|
||||
|
|
|
|||
|
|
@ -370,6 +370,11 @@
|
|||
<tp:docstring>
|
||||
The device's carrier/link changed.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
<tp:enumvalue suffix="CONNECTION_ASSUMED" value="41">
|
||||
<tp:docstring>
|
||||
The device's existing connection was assumed.
|
||||
</tp:docstring>
|
||||
</tp:enumvalue>
|
||||
</tp:enum>
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ typedef struct {
|
|||
GSList *share_rules;
|
||||
|
||||
char *ac_path;
|
||||
|
||||
gboolean assumed;
|
||||
} NMActRequestPrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -136,6 +138,7 @@ NMActRequest *
|
|||
nm_act_request_new (NMConnection *connection,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gboolean assumed,
|
||||
gpointer *device)
|
||||
{
|
||||
GObject *object;
|
||||
|
|
@ -160,6 +163,7 @@ nm_act_request_new (NMConnection *connection,
|
|||
NM_ACT_REQUEST (object));
|
||||
|
||||
priv->user_requested = user_requested;
|
||||
priv->assumed = assumed;
|
||||
|
||||
return NM_ACT_REQUEST (object);
|
||||
}
|
||||
|
|
@ -643,3 +647,11 @@ nm_act_request_get_device (NMActRequest *req)
|
|||
return G_OBJECT (NM_ACT_REQUEST_GET_PRIVATE (req)->device);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_act_request_get_assumed (NMActRequest *req)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
|
||||
|
||||
return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ GType nm_act_request_get_type (void);
|
|||
NMActRequest *nm_act_request_new (NMConnection *connection,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gboolean assumed,
|
||||
gpointer *device); /* An NMDevice */
|
||||
|
||||
NMConnection *nm_act_request_get_connection (NMActRequest *req);
|
||||
|
|
@ -85,6 +86,8 @@ void nm_act_request_add_share_rule (NMActRequest *req,
|
|||
|
||||
GObject * nm_act_request_get_device (NMActRequest *req);
|
||||
|
||||
gboolean nm_act_request_get_assumed (NMActRequest *req);
|
||||
|
||||
gboolean nm_act_request_get_secrets (NMActRequest *req,
|
||||
const char *setting_name,
|
||||
gboolean request_new,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -113,6 +113,14 @@ static void add_device (NMManager *self, NMDevice *device);
|
|||
|
||||
static void hostname_provider_init (NMHostnameProvider *provider_class);
|
||||
|
||||
static const char *internal_activate_device (NMManager *manager,
|
||||
NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gboolean assumed,
|
||||
GError **error);
|
||||
|
||||
#define SSD_POKE_INTERVAL 120
|
||||
#define ORIGDEV_TAG "originating-device"
|
||||
|
||||
|
|
@ -1165,7 +1173,6 @@ add_device (NMManager *self, NMDevice *device)
|
|||
char *path;
|
||||
static guint32 devcount = 0;
|
||||
const GSList *unmanaged_specs;
|
||||
GSList *connections = NULL;
|
||||
NMConnection *existing;
|
||||
GHashTableIter iter;
|
||||
gpointer value;
|
||||
|
|
@ -1208,20 +1215,47 @@ add_device (NMManager *self, NMDevice *device)
|
|||
/* Check if we should assume the device's active connection by matching its
|
||||
* config with an existing system connection.
|
||||
*/
|
||||
g_hash_table_iter_init (&iter, priv->system_connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
connections = g_slist_append (connections, value);
|
||||
existing = nm_device_interface_connection_match_config (NM_DEVICE_INTERFACE (device),
|
||||
(const GSList *) connections);
|
||||
g_slist_free (connections);
|
||||
if (nm_device_interface_can_assume_connection (NM_DEVICE_INTERFACE (device))) {
|
||||
GSList *connections = NULL;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->system_connections);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||
connections = g_slist_append (connections, value);
|
||||
existing = nm_device_interface_connection_match_config (NM_DEVICE_INTERFACE (device),
|
||||
(const GSList *) connections);
|
||||
g_slist_free (connections);
|
||||
}
|
||||
|
||||
/* Start the device if it's supposed to be managed */
|
||||
unmanaged_specs = nm_sysconfig_settings_get_unmanaged_specs (priv->sys_settings);
|
||||
if (!priv->sleeping && !nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs))
|
||||
nm_device_set_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
||||
if ( !priv->sleeping
|
||||
&& !nm_device_interface_spec_match_list (NM_DEVICE_INTERFACE (device), unmanaged_specs)) {
|
||||
nm_device_set_managed (device,
|
||||
TRUE,
|
||||
existing ? NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED :
|
||||
NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
||||
}
|
||||
|
||||
nm_sysconfig_settings_device_added (priv->sys_settings, device);
|
||||
g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
|
||||
|
||||
/* If the device has a connection it can assume, do that now */
|
||||
if (existing) {
|
||||
const char *ac_path;
|
||||
GError *error = NULL;
|
||||
|
||||
ac_path = internal_activate_device (self, device, existing, NULL, FALSE, TRUE, &error);
|
||||
if (ac_path)
|
||||
g_object_notify (G_OBJECT (self), NM_MANAGER_ACTIVE_CONNECTIONS);
|
||||
else {
|
||||
nm_warning ("Assumed connection (%d) %s failed to activate: (%d) %s",
|
||||
nm_connection_get_scope (existing),
|
||||
nm_connection_get_path (existing),
|
||||
error ? error->code : -1,
|
||||
error && error->message ? error->message : "(unknown)");
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -1826,6 +1860,7 @@ internal_activate_device (NMManager *manager,
|
|||
NMConnection *connection,
|
||||
const char *specific_object,
|
||||
gboolean user_requested,
|
||||
gboolean assumed,
|
||||
GError **error)
|
||||
{
|
||||
NMActRequest *req;
|
||||
|
|
@ -1849,7 +1884,7 @@ internal_activate_device (NMManager *manager,
|
|||
NM_DEVICE_STATE_REASON_NONE);
|
||||
}
|
||||
|
||||
req = nm_act_request_new (connection, specific_object, user_requested, (gpointer) device);
|
||||
req = nm_act_request_new (connection, specific_object, user_requested, assumed, (gpointer) device);
|
||||
g_signal_connect (req, "manager-get-secrets", G_CALLBACK (provider_get_secrets), manager);
|
||||
g_signal_connect (req, "manager-cancel-secrets", G_CALLBACK (provider_cancel_secrets), manager);
|
||||
success = nm_device_interface_activate (dev_iface, req, error);
|
||||
|
|
@ -1961,6 +1996,7 @@ nm_manager_activate_connection (NMManager *manager,
|
|||
connection,
|
||||
specific_object,
|
||||
user_requested,
|
||||
FALSE,
|
||||
error);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue