Commit 87a3df2e authored by Thomas Haller's avatar Thomas Haller

device: remove default-unmanaged and refactor unmanaged flags

Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between
unmanaged flags, device state and managed property.

Previously, the NM_UNMANAGED_DEFAULT was special in that a device was
still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag
set and its state was managed. Thus, whether the device (state) was managed,
depended on the device state too.

Now, a device is considered managed (or unmanaged) based on the unmanaged
flags and realization state alone. At the same time, the device state
directly corresponds to the managed property of the device. Of course,
while changing the unmanaged flags, that invariant is shortly violated
until the state transistion is complete.

Introduce more unmanaged flags whereas some of them are non-authorative.
For example, the EXTERNAL_DOWN flag has only effect as long as the user
didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other
words, certain flags can render other flags ineffective. Whether the device
is considered managed depends on the flags but also at the explicitly unset flags.
In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored
(if no other flags were present).

Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected
state would transition back to unmanaged. No longer do that. Once a device is
managed, it stays managed as long as the flags indicate it should be managed.
However, the user can also modify the unmanaged flags via the D-Bus API.

Also get rid or nm_device_finish_init(). That was previously called
by NMManager after add_device(). As we now realize devices (possibly
multiple times) this should be handled during realization.

https://bugzilla.gnome.org/show_bug.cgi?id=746566
parent 2a17dbf4
......@@ -138,7 +138,7 @@ constructor (GType type,
n_construct_params,
construct_params);
nm_device_set_unmanaged_flags_initial (NM_DEVICE (object), NM_UNMANAGED_DEFAULT, TRUE);
nm_device_set_unmanaged_flags ((NMDevice *) object, NM_UNMANAGED_BY_DEFAULT, TRUE);
return object;
}
......
......@@ -127,7 +127,7 @@ parent_state_changed (NMDevice *parent,
if (reason == NM_DEVICE_STATE_REASON_CARRIER)
return;
nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason);
nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason);
}
static void
......@@ -153,7 +153,7 @@ nm_device_macvlan_set_parent (NMDeviceMacvlan *self, NMDevice *parent)
/* Set parent-dependent unmanaged flag */
nm_device_set_unmanaged_by_flags (device,
NM_UNMANAGED_PARENT,
!nm_device_get_managed (parent),
!nm_device_get_managed (parent, FALSE),
NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
}
......
......@@ -95,7 +95,6 @@ void nm_device_master_check_slave_physical_port (NMDevice *self, NMDevice *slave
void nm_device_set_carrier (NMDevice *self, gboolean carrier);
void nm_device_emit_recheck_auto_activate (NMDevice *device);
void nm_device_queue_recheck_assume (NMDevice *device);
void nm_device_queue_recheck_available (NMDevice *device,
NMDeviceStateReason available_reason,
......
......@@ -77,7 +77,7 @@ parent_state_changed (NMDevice *parent,
if (reason == NM_DEVICE_STATE_REASON_CARRIER)
return;
nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason);
nm_device_set_unmanaged_by_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent, FALSE), reason);
}
static void
......@@ -147,7 +147,7 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent)
/* Set parent-dependent unmanaged flag */
nm_device_set_unmanaged_by_flags (device,
NM_UNMANAGED_PARENT,
!nm_device_get_managed (parent),
!nm_device_get_managed (parent, FALSE),
NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
}
......
This diff is collapsed.
......@@ -326,8 +326,6 @@ typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device,
GType nm_device_get_type (void);
void nm_device_finish_init (NMDevice *device);
const char * nm_device_get_udi (NMDevice *dev);
const char * nm_device_get_iface (NMDevice *dev);
int nm_device_get_ifindex (NMDevice *dev);
......@@ -424,44 +422,64 @@ RfKillType nm_device_get_rfkill_type (NMDevice *device);
/**
* NMUnmanagedFlags:
* @NM_UNMANAGED_NONE: placeholder value
* @NM_UNMANAGED_INTERNAL: %TRUE when unmanaged by internal decision (ie,
* because NM is sleeping or not managed for some other reason)
* @NM_UNMANAGED_SLEEPING: %TRUE when unmanaged because NM is sleeping.
* @NM_UNMANAGED_QUITTING: %TRUE when unmanaged because NM is shutting down.
* @NM_UNMANAGED_PARENT: %TRUE when unmanaged due to parent device being unmanaged
* @NM_UNMANAGED_LOOPBACK: %TRUE for unmanaging loopback device
* @NM_UNMANAGED_PLATFORM_INIT: %TRUE when unmanaged because platform link not
* yet initialized
* @NM_UNMANAGED_USER: %TRUE when unmanaged by user decision (via unmanaged-specs)
* @NM_UNMANAGED_DEFAULT: %TRUE when unmanaged by default (ie, Generic devices)
* yet initialized. Unrealized device are also unmanaged for this reason.
* @NM_UNMANAGED_USER_EXPLICIT: %TRUE when unmanaged by explicit user decision
* (e.g. via a D-Bus command)
* @NM_UNMANAGED_BY_DEFAULT: %TRUE for certain device types where we unmanage
* them by default
* @NM_UNMANAGED_USER_CONFIG: %TRUE when unmanaged by user decision (via unmanaged-specs)
* @NM_UNMANAGED_USER_UDEV: %TRUE when unmanaged by user decision (via UDev rule)
* @NM_UNMANAGED_EXTERNAL_DOWN: %TRUE when unmanaged because !IFF_UP and not created by NM
* @NM_UNMANAGED_IS_SLAVE: indicates that the device is enslaved. Note that
* setting the NM_UNMANAGED_IS_SLAVE to %TRUE makes no sense, this flag has only
* meaning to set a slave device as managed if the parent is managed too.
*/
typedef enum { /*< skip >*/
NM_UNMANAGED_NONE = 0,
NM_UNMANAGED_INTERNAL = (1LL << 0),
NM_UNMANAGED_PARENT = (1LL << 1),
NM_UNMANAGED_LOOPBACK = (1LL << 2),
NM_UNMANAGED_PLATFORM_INIT = (1LL << 3),
NM_UNMANAGED_USER = (1LL << 4),
NM_UNMANAGED_DEFAULT = (1LL << 8),
/* these flags are authorative. If one of them is set,
* the device cannot be managed. */
NM_UNMANAGED_SLEEPING = (1LL << 0),
NM_UNMANAGED_QUITTING = (1LL << 1),
NM_UNMANAGED_PARENT = (1LL << 2),
NM_UNMANAGED_LOOPBACK = (1LL << 3),
NM_UNMANAGED_PLATFORM_INIT = (1LL << 4),
NM_UNMANAGED_USER_EXPLICIT = (1LL << 5),
/* These flags can be non-effective and be overwritten
* by other flags. */
NM_UNMANAGED_BY_DEFAULT = (1LL << 8),
NM_UNMANAGED_USER_CONFIG = (1LL << 9),
NM_UNMANAGED_USER_UDEV = (1LL << 10),
NM_UNMANAGED_EXTERNAL_DOWN = (1LL << 11),
NM_UNMANAGED_IS_SLAVE = (1LL << 12),
/* Boundary value */
__NM_UNMANAGED_LAST,
NM_UNMANAGED_LAST = __NM_UNMANAGED_LAST - 1,
NM_UNMANAGED_ALL = ((NM_UNMANAGED_LAST << 1) - 1),
} NMUnmanagedFlags;
gboolean nm_device_get_managed (NMDevice *device);
typedef enum {
NM_UNMAN_FLAG_OP_SET_MANAGED = FALSE,
NM_UNMAN_FLAG_OP_SET_UNMANAGED = TRUE,
NM_UNMAN_FLAG_OP_FORGET = 2,
} NMUnmanFlagOp;
const char *nm_unmanaged_flags2str (NMUnmanagedFlags flags, char *buf, gsize len);
gboolean nm_device_get_managed (NMDevice *device, gboolean for_user_request);
NMUnmanagedFlags nm_device_get_unmanaged_flags (NMDevice *device, NMUnmanagedFlags flag);
void nm_device_set_unmanaged_flags (NMDevice *device,
NMUnmanagedFlags flags,
NMUnmanFlagOp set_op);
void nm_device_set_unmanaged_by_flags (NMDevice *device,
NMUnmanagedFlags flag,
gboolean unmanaged,
NMUnmanagedFlags flags,
NMUnmanFlagOp set_op,
NMDeviceStateReason reason);
void nm_device_set_unmanaged_by_user_config (NMDevice *self, const GSList *unmanaged_specs);
void nm_device_set_unmanaged_flags_initial (NMDevice *device,
NMUnmanagedFlags flag,
gboolean unmanaged);
void nm_device_set_unmanaged_by_user_udev (NMDevice *self);
void nm_device_set_unmanaged_by_quitting (NMDevice *device);
gboolean nm_device_get_is_nm_owned (NMDevice *device);
......@@ -484,6 +502,7 @@ gboolean nm_device_unrealize (NMDevice *device,
gboolean nm_device_get_autoconnect (NMDevice *device);
void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect);
void nm_device_emit_recheck_auto_activate (NMDevice *device);
void nm_device_state_changed (NMDevice *device,
NMDeviceState state,
......
......@@ -833,9 +833,9 @@ remove_device (NMManager *manager,
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
nm_log_dbg (LOGD_DEVICE, "(%s): removing device (allow_unmanage %d, managed %d)",
nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device));
nm_device_get_iface (device), allow_unmanage, nm_device_get_managed (device, FALSE));
if (allow_unmanage && nm_device_get_managed (device)) {
if (allow_unmanage && nm_device_get_managed (device, FALSE)) {
NMActRequest *req = nm_device_get_act_request (device);
gboolean unmanage = FALSE;
......@@ -855,7 +855,7 @@ remove_device (NMManager *manager,
if (quitting)
nm_device_set_unmanaged_by_quitting (device);
else
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_REMOVED);
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, TRUE, NM_DEVICE_STATE_REASON_REMOVED);
} else if (quitting && nm_config_get_configure_and_quit (nm_config_get ())) {
nm_device_spawn_iface_helper (device);
}
......@@ -1663,14 +1663,6 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn
return TRUE;
}
static gboolean
can_start_device (NMManager *self, NMDevice *device)
{
return nm_device_is_real (device)
&& !manager_sleeping (self)
&& !nm_device_get_unmanaged_flags (device, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT);
}
static gboolean
recheck_assume_connection (NMManager *self, NMDevice *device)
{
......@@ -1684,7 +1676,7 @@ recheck_assume_connection (NMManager *self, NMDevice *device)
if (nm_device_get_is_nm_owned (device))
return FALSE;
if (!can_start_device (self, device))
if (!nm_device_get_managed (device, FALSE))
return FALSE;
state = nm_device_get_state (device);
......@@ -1711,13 +1703,6 @@ recheck_assume_connection (NMManager *self, NMDevice *device)
nm_device_state_changed (device,
NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
/* Return default-unmanaged devices to their original state */
if (nm_device_get_unmanaged_flags (device, NM_UNMANAGED_DEFAULT)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_UNMANAGED,
NM_DEVICE_STATE_REASON_CONFIG_FAILED);
}
}
if (generated) {
......@@ -1779,26 +1764,31 @@ device_realized (NMDevice *device,
GParamSpec *pspec,
NMManager *self)
{
int ifindex;
/* Emit D-Bus signals */
g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES);
}
/* Loopback device never gets managed */
ifindex = nm_device_get_ifindex (device);
if (ifindex > 0 && nm_platform_link_get_type (NM_PLATFORM_GET, ifindex) == NM_LINK_TYPE_LOOPBACK)
static void
_device_realize_finish (NMManager *self, NMDevice *device, const NMPlatformLink *plink)
{
g_return_if_fail (NM_IS_MANAGER (self));
g_return_if_fail (NM_IS_DEVICE (device));
nm_device_realize_finish (device, plink);
if (!nm_device_get_managed (device, FALSE))
return;
if (!can_start_device (self, device))
if (recheck_assume_connection (self, device))
return;
if ( !recheck_assume_connection (self, device)
&& nm_device_get_managed (device)) {
nm_device_state_changed (device,
NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_NOW_MANAGED);
}
/* if we failed to assume a connection for the managed device, but the device
* is still unavailable. Set UNAVAILABLE state again, this time with NOW_MANAGED. */
nm_device_state_changed (device,
NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_NOW_MANAGED);
nm_device_emit_recheck_auto_activate (device);
}
/**
......@@ -1815,7 +1805,6 @@ add_device (NMManager *self, NMDevice *device, GError **error)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
const char *iface, *type_desc;
const GSList *unmanaged_specs;
RfKillType rtype;
GSList *iter, *remove = NULL;
int ifindex;
......@@ -1898,19 +1887,15 @@ add_device (NMManager *self, NMDevice *device, GError **error)
type_desc = nm_device_get_type_desc (device);
g_assert (type_desc);
unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
nm_device_set_unmanaged_flags_initial (device,
NM_UNMANAGED_USER,
nm_device_spec_match_list (device, unmanaged_specs));
nm_device_set_unmanaged_flags_initial (device,
NM_UNMANAGED_INTERNAL,
manager_sleeping (self));
nm_device_set_unmanaged_by_user_config (device, nm_settings_get_unmanaged_specs (priv->settings));
nm_device_set_unmanaged_flags (device,
NM_UNMANAGED_SLEEPING,
manager_sleeping (self));
dbus_path = nm_exported_object_export (NM_EXPORTED_OBJECT (device));
nm_log_info (LOGD_DEVICE, "(%s): new %s device (%s)", iface, type_desc, dbus_path);
nm_device_finish_init (device);
nm_settings_device_added (priv->settings, device);
g_signal_emit (self, signals[INTERNAL_DEVICE_ADDED], 0, device);
g_object_notify (G_OBJECT (self), NM_MANAGER_ALL_DEVICES);
......@@ -1937,11 +1922,14 @@ factory_device_added_cb (NMDeviceFactory *factory,
NMDevice *device,
gpointer user_data)
{
NMManager *self = user_data;
GError *error = NULL;
g_return_if_fail (NM_IS_MANAGER (self));
if (nm_device_realize_start (device, NULL, NULL, &error)) {
add_device (NM_MANAGER (user_data), device, NULL);
nm_device_realize_finish (device, NULL);
add_device (self, device, NULL);
_device_realize_finish (self, device, NULL);
} else {
nm_log_warn (LOGD_DEVICE, "(%s): failed to realize device: %s",
nm_device_get_iface (device), error->message);
......@@ -2013,7 +2001,7 @@ platform_link_added (NMManager *self,
return;
} else if (nm_device_realize_start (candidate, plink, &compatible, &error)) {
/* Success */
nm_device_realize_finish (candidate, plink);
_device_realize_finish (self, candidate, plink);
return;
}
......@@ -2062,7 +2050,7 @@ platform_link_added (NMManager *self,
nm_device_set_nm_plugin_missing (device, TRUE);
if (nm_device_realize_start (device, plink, NULL, &error)) {
add_device (self, device, NULL);
nm_device_realize_finish (device, plink);
_device_realize_finish (self, device, plink);
} else {
nm_log_warn (LOGD_DEVICE, "%s: failed to realize device: %s",
plink->name, error->message);
......@@ -2849,6 +2837,16 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
if (existing)
nm_device_steal_connection (existing, connection);
/* when creating the software device, it can happen that the device is
* still unmanaged by NM_UNMANAGED_PLATFORM_INIT because we didn't yet
* get the udev event. At this point, we can no longer delay the activation
* and force the device to be managed. */
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_PLATFORM_INIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_USER_EXPLICIT, FALSE, NM_DEVICE_STATE_REASON_USER_REQUESTED);
g_return_val_if_fail (nm_device_get_managed (device, FALSE), FALSE);
if (nm_device_get_state (device) == NM_DEVICE_STATE_UNMANAGED) {
nm_device_state_changed (device,
NM_DEVICE_STATE_UNAVAILABLE,
......@@ -3809,7 +3807,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
if (suspending && device_is_wake_on_lan (device))
continue;
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
}
} else {
nm_log_info (LOGD_SUSPEND, "%s...", waking_from_suspend ? "waking up" : "re-enabling");
......@@ -3824,7 +3822,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
if (nm_device_is_software (device))
continue;
if (device_is_wake_on_lan (device))
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_INTERNAL, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
}
}
......@@ -3860,7 +3858,7 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
nm_device_set_autoconnect (device, TRUE);
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_INTERNAL, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, FALSE, NM_DEVICE_STATE_REASON_NOW_MANAGED);
}
}
......@@ -4433,9 +4431,6 @@ handle_firmware_changed (gpointer user_data)
priv->fw_changed_id = 0;
if (manager_sleeping (self))
return FALSE;
/* Try to re-enable devices with missing firmware */
for (iter = priv->devices; iter; iter = iter->next) {
NMDevice *candidate = NM_DEVICE (iter->data);
......
......@@ -1881,7 +1881,7 @@ device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
/* If the device isn't managed or it already has a default wired connection,
* ignore it.
*/
if ( !nm_device_get_managed (device)
if ( !nm_device_get_managed (device, FALSE)
|| g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_CONNECTION_TAG)
|| have_connection_for_device (self, device))
return;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment