mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-21 09:30:39 +01:00
core: merge branch 'th/queue_act_request_no_carrier_rh1079353'
https://bugzilla.redhat.com/show_bug.cgi?id=1079353
This commit is contained in:
commit
1f5b9ffc3d
11 changed files with 263 additions and 157 deletions
|
|
@ -187,6 +187,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
|||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device);
|
||||
|
|
@ -929,7 +930,7 @@ bluez_device_removed (NMBluezDevice *bdev, gpointer user_data)
|
|||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *dev)
|
||||
is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
NMDeviceBt *self = NM_DEVICE_BT (dev);
|
||||
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self);
|
||||
|
|
@ -957,7 +958,7 @@ handle_availability_change (NMDeviceBt *self,
|
|||
return;
|
||||
}
|
||||
|
||||
available = nm_device_is_available (device);
|
||||
available = nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
|
||||
if (available == old_available)
|
||||
return;
|
||||
|
||||
|
|
@ -987,7 +988,7 @@ set_mm_running (NMDeviceBt *self, gboolean running)
|
|||
_LOGD (LOGD_BT, "ModemManager now %s",
|
||||
running ? "available" : "unavailable");
|
||||
|
||||
old_available = nm_device_is_available (NM_DEVICE (self));
|
||||
old_available = nm_device_is_available (NM_DEVICE (self), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
|
||||
priv->mm_running = running;
|
||||
handle_availability_change (self, old_available, NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE);
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ get_generic_capabilities (NMDevice *dev)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *dev)
|
||||
is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
if (NM_DEVICE_GET_CLASS (dev)->is_up)
|
||||
return NM_DEVICE_GET_CLASS (dev)->is_up (dev);
|
||||
|
|
@ -78,6 +78,7 @@ is_available (NMDevice *dev)
|
|||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
/* Connections are always available because the carrier state is determined
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ get_generic_capabilities (NMDevice *dev)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *dev)
|
||||
is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
if (NM_DEVICE_GET_CLASS (dev)->is_up)
|
||||
return NM_DEVICE_GET_CLASS (dev)->is_up (dev);
|
||||
|
|
@ -76,6 +76,7 @@ is_available (NMDevice *dev)
|
|||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
/* Connections are always available because the carrier state is determined
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ typedef struct {
|
|||
guint32 ip4_address;
|
||||
|
||||
NMActRequest * queued_act_request;
|
||||
gboolean queued_act_request_is_waiting_for_carrier;
|
||||
NMActRequest * act_request;
|
||||
guint act_source_id;
|
||||
gpointer act_source_func;
|
||||
|
|
@ -338,6 +339,8 @@ static gboolean addrconf6_start_with_link_ready (NMDevice *self);
|
|||
static gboolean dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection);
|
||||
static NMActStageReturn linklocal6_start (NMDevice *self);
|
||||
|
||||
static void _carrier_wait_check_queued_act_request (NMDevice *self);
|
||||
|
||||
static gboolean nm_device_get_default_unmanaged (NMDevice *self);
|
||||
|
||||
static void _set_state_full (NMDevice *self,
|
||||
|
|
@ -1138,6 +1141,7 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier)
|
|||
g_source_remove (priv->carrier_wait_id);
|
||||
priv->carrier_wait_id = 0;
|
||||
nm_device_remove_pending_action (self, "carrier wait", TRUE);
|
||||
_carrier_wait_check_queued_act_request (self);
|
||||
}
|
||||
} else if (state <= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
_LOGI (LOGD_DEVICE, "link disconnected");
|
||||
|
|
@ -1734,16 +1738,24 @@ nm_device_removed (NMDevice *self)
|
|||
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *self)
|
||||
is_available (NMDevice *self, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
return priv->carrier || priv->ignore_carrier;
|
||||
if (priv->carrier || priv->ignore_carrier)
|
||||
return TRUE;
|
||||
|
||||
if (NM_FLAGS_HAS (flags, NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_is_available:
|
||||
* @self: the #NMDevice
|
||||
* @flags: additional flags to influence the check. Flags have the
|
||||
* meaning to increase the availability of a device.
|
||||
*
|
||||
* Checks if @self would currently be capable of activating a
|
||||
* connection. In particular, it checks that the device is ready (eg,
|
||||
|
|
@ -1759,14 +1771,14 @@ is_available (NMDevice *self)
|
|||
* Returns: %TRUE or %FALSE
|
||||
*/
|
||||
gboolean
|
||||
nm_device_is_available (NMDevice *self)
|
||||
nm_device_is_available (NMDevice *self, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->firmware_missing)
|
||||
return FALSE;
|
||||
|
||||
return NM_DEVICE_GET_CLASS (self)->is_available (self);
|
||||
return NM_DEVICE_GET_CLASS (self)->is_available (self, flags);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -1890,7 +1902,7 @@ can_auto_connect (NMDevice *self,
|
|||
if (!nm_setting_connection_get_autoconnect (s_con))
|
||||
return FALSE;
|
||||
|
||||
return nm_device_connection_is_available (self, connection, FALSE);
|
||||
return nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -5622,6 +5634,15 @@ disconnect_cb (NMDevice *self,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_clear_queued_act_request (NMDevicePrivate *priv)
|
||||
{
|
||||
if (priv->queued_act_request) {
|
||||
nm_active_connection_set_state ((NMActiveConnection *) priv->queued_act_request, NM_ACTIVE_CONNECTION_STATE_DEACTIVATED);
|
||||
g_clear_object (&priv->queued_act_request);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context)
|
||||
{
|
||||
|
|
@ -5724,26 +5745,97 @@ _device_activate (NMDevice *self, NMActRequest *req)
|
|||
nm_device_activate_schedule_stage1_device_prepare (self);
|
||||
}
|
||||
|
||||
static void
|
||||
_carrier_wait_check_queued_act_request (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMActRequest *queued_req;
|
||||
|
||||
if ( !priv->queued_act_request
|
||||
|| !priv->queued_act_request_is_waiting_for_carrier)
|
||||
return;
|
||||
|
||||
priv->queued_act_request_is_waiting_for_carrier = FALSE;
|
||||
if (!priv->carrier) {
|
||||
_LOGD (LOGD_DEVICE, "Cancel queued activation request as we have no carrier after timeout");
|
||||
g_clear_object (&priv->queued_act_request);
|
||||
} else {
|
||||
_LOGD (LOGD_DEVICE, "Activate queued activation request as we now have carrier");
|
||||
queued_req = priv->queued_act_request;
|
||||
priv->queued_act_request = NULL;
|
||||
_device_activate (self, queued_req);
|
||||
g_object_unref (queued_req);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMConnection *connection;
|
||||
|
||||
/* If we have carrier or if we are not waiting for it, the activation
|
||||
* request is not blocked waiting for carrier. */
|
||||
if (priv->carrier)
|
||||
return FALSE;
|
||||
if (priv->carrier_wait_id == 0)
|
||||
return FALSE;
|
||||
|
||||
connection = nm_act_request_get_connection (req);
|
||||
|
||||
if (!nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL, NULL)) {
|
||||
/* We passed all @flags we have, and no @specific_object.
|
||||
* This equals maximal availability, if a connection is not available
|
||||
* in this case, it is not waiting for carrier.
|
||||
*
|
||||
* Actually, why are we even trying to activate it? Strange, but whatever
|
||||
* the reason, don't wait for carrier.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_ALL & ~_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER, NULL)) {
|
||||
/* The connection was available with flags ALL, and it is still available
|
||||
* if we pretend not to wait for carrier. That means that the
|
||||
* connection is available now, and does not wait for carrier.
|
||||
*
|
||||
* Since the flags increase the availability of a connection, when checking
|
||||
* ALL&~WAITING_CARRIER, it means that we certainly would wait for carrier. */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The activation request must wait for carrier. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nm_device_queue_activation (NMDevice *self, NMActRequest *req)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
gboolean must_queue;
|
||||
|
||||
if (!priv->act_request) {
|
||||
must_queue = _carrier_wait_check_act_request_must_queue (self, req);
|
||||
|
||||
if (!priv->act_request && !must_queue) {
|
||||
/* Just activate immediately */
|
||||
_device_activate (self, req);
|
||||
return;
|
||||
}
|
||||
|
||||
/* supercede any already-queued request */
|
||||
g_clear_object (&priv->queued_act_request);
|
||||
_clear_queued_act_request (priv);
|
||||
priv->queued_act_request = g_object_ref (req);
|
||||
priv->queued_act_request_is_waiting_for_carrier = must_queue;
|
||||
|
||||
/* Deactivate existing activation request first */
|
||||
_LOGI (LOGD_DEVICE, "disconnecting for new activation request.");
|
||||
nm_device_state_changed (self,
|
||||
NM_DEVICE_STATE_DEACTIVATING,
|
||||
NM_DEVICE_STATE_REASON_NONE);
|
||||
_LOGD (LOGD_DEVICE, "queue activation request waiting for %s", must_queue ? "carrier" : "currently active connection to disconnect");
|
||||
|
||||
if (priv->act_request) {
|
||||
/* Deactivate existing activation request first */
|
||||
_LOGI (LOGD_DEVICE, "disconnecting for new activation request.");
|
||||
nm_device_state_changed (self,
|
||||
NM_DEVICE_STATE_DEACTIVATING,
|
||||
NM_DEVICE_STATE_REASON_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -6285,6 +6377,9 @@ carrier_wait_timeout (gpointer user_data)
|
|||
|
||||
NM_DEVICE_GET_PRIVATE (self)->carrier_wait_id = 0;
|
||||
nm_device_remove_pending_action (self, "carrier wait", TRUE);
|
||||
|
||||
_carrier_wait_check_queued_act_request (self);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
|
@ -6349,12 +6444,11 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
|
|||
* a timeout is reached.
|
||||
*/
|
||||
if (device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
|
||||
if (priv->carrier_wait_id) {
|
||||
if (priv->carrier_wait_id)
|
||||
g_source_remove (priv->carrier_wait_id);
|
||||
nm_device_remove_pending_action (self, "carrier wait", TRUE);
|
||||
}
|
||||
else
|
||||
nm_device_add_pending_action (self, "carrier wait", TRUE);
|
||||
priv->carrier_wait_id = g_timeout_add_seconds (5, carrier_wait_timeout, self);
|
||||
nm_device_add_pending_action (self, "carrier wait", TRUE);
|
||||
}
|
||||
|
||||
/* Can only get HW address of some devices when they are up */
|
||||
|
|
@ -6880,48 +6974,45 @@ nm_device_set_dhcp_anycast_address (NMDevice *self, const char *addr)
|
|||
}
|
||||
|
||||
/**
|
||||
* nm_device_connection_is_available():
|
||||
* nm_device_check_connection_available():
|
||||
* @self: the #NMDevice
|
||||
* @connection: the #NMConnection to check for availability
|
||||
* @allow_device_override: set to %TRUE to let the device do specific checks
|
||||
* @flags: flags to affect the decision making of whether a connection
|
||||
* is available. Adding a flag can only make a connection more available,
|
||||
* not less.
|
||||
* @specific_object: a device type dependent argument to further
|
||||
* filter the result. Passing a non %NULL specific object can only reduce
|
||||
* the availability of a connection.
|
||||
*
|
||||
* Check if @connection is available to be activated on @self. Normally this
|
||||
* only checks if the connection is in @self's AvailableConnections property.
|
||||
* If @allow_device_override is %TRUE then the device is asked to do specific
|
||||
* checks that may bypass the AvailableConnections property.
|
||||
* Check if @connection is available to be activated on @self.
|
||||
*
|
||||
* Returns: %TRUE if @connection can be activated on @self
|
||||
*/
|
||||
gboolean
|
||||
nm_device_connection_is_available (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
gboolean allow_device_override)
|
||||
nm_device_check_connection_available (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
gboolean available = FALSE;
|
||||
NMDeviceState state;
|
||||
|
||||
if (nm_device_get_default_unmanaged (self) && (priv->state == NM_DEVICE_STATE_UNMANAGED)) {
|
||||
/* default-unmanaged devices in UNMANAGED state have no available connections
|
||||
* so we must manually check whether the connection is available here.
|
||||
*/
|
||||
if ( nm_device_check_connection_compatible (self, connection)
|
||||
&& NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, NULL))
|
||||
return TRUE;
|
||||
}
|
||||
state = nm_device_get_state (self);
|
||||
if (state < NM_DEVICE_STATE_UNMANAGED)
|
||||
return FALSE;
|
||||
if ( state < NM_DEVICE_STATE_UNAVAILABLE
|
||||
&& nm_device_get_unmanaged_flag (self, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT))
|
||||
return FALSE;
|
||||
if ( state < NM_DEVICE_STATE_DISCONNECTED
|
||||
&& ( ( !NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
|
||||
&& !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE))
|
||||
|| ( NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
|
||||
&& !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER))))
|
||||
return FALSE;
|
||||
|
||||
available = !!g_hash_table_lookup (priv->available_connections, connection);
|
||||
if (!available && allow_device_override) {
|
||||
/* FIXME: hack for hidden WiFi becuase clients didn't consistently
|
||||
* set the 'hidden' property to indicate hidden SSID networks. If
|
||||
* activating but the network isn't available let the device recheck
|
||||
* availability.
|
||||
*/
|
||||
if ( nm_device_check_connection_compatible (self, connection)
|
||||
&& NM_DEVICE_GET_CLASS (self)->check_connection_available_wifi_hidden)
|
||||
available = NM_DEVICE_GET_CLASS (self)->check_connection_available_wifi_hidden (self, connection);
|
||||
}
|
||||
if (!nm_device_check_connection_compatible (self, connection))
|
||||
return FALSE;
|
||||
|
||||
return available;
|
||||
return NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, flags, specific_object);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -6941,17 +7032,10 @@ _clear_available_connections (NMDevice *self, gboolean do_signal)
|
|||
static gboolean
|
||||
_try_add_available_connection (NMDevice *self, NMConnection *connection)
|
||||
{
|
||||
if ( nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED
|
||||
&& !nm_device_get_default_unmanaged (self))
|
||||
return FALSE;
|
||||
|
||||
if (nm_device_check_connection_compatible (self, connection)) {
|
||||
if (NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, NULL)) {
|
||||
g_hash_table_insert (NM_DEVICE_GET_PRIVATE (self)->available_connections,
|
||||
g_object_ref (connection),
|
||||
GUINT_TO_POINTER (1));
|
||||
return TRUE;
|
||||
}
|
||||
if (nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, NULL)) {
|
||||
g_hash_table_add (NM_DEVICE_GET_PRIVATE (self)->available_connections,
|
||||
g_object_ref (connection));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -6965,15 +7049,28 @@ _del_available_connection (NMDevice *self, NMConnection *connection)
|
|||
static gboolean
|
||||
check_connection_available (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
|
||||
|
||||
/* Connections which require a network connection are not available when
|
||||
* the device has no carrier, even with ignore-carrer=TRUE.
|
||||
*/
|
||||
if (NM_DEVICE_GET_PRIVATE (self)->carrier == FALSE)
|
||||
return connection_requires_carrier (connection) ? FALSE : TRUE;
|
||||
if ( priv->carrier
|
||||
|| !connection_requires_carrier (connection))
|
||||
return TRUE;
|
||||
|
||||
return TRUE;
|
||||
if ( NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER)
|
||||
&& priv->carrier_wait_id != 0) {
|
||||
/* The device has no carrier though the connection requires it.
|
||||
*
|
||||
* If we are still waiting for carrier, the connection is available
|
||||
* for an explicit user-request. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -7025,8 +7122,8 @@ nm_device_get_available_connections (NMDevice *self, const char *specific_object
|
|||
/* If a specific object is given, only include connections that are
|
||||
* compatible with it.
|
||||
*/
|
||||
if ( !specific_object
|
||||
|| NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, specific_object))
|
||||
if ( !specific_object /* << Optimization: we know that the connection is available without @specific_object. */
|
||||
|| nm_device_check_connection_available (self, connection, NM_DEVICE_CHECK_CON_AVAILABLE_NONE, specific_object))
|
||||
g_ptr_array_add (array, connection);
|
||||
}
|
||||
}
|
||||
|
|
@ -7635,7 +7732,7 @@ _set_state_full (NMDevice *self,
|
|||
|
||||
if (state <= NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
_clear_available_connections (self, TRUE);
|
||||
g_clear_object (&priv->queued_act_request);
|
||||
_clear_queued_act_request (priv);
|
||||
}
|
||||
|
||||
/* Update the available connections list when a device first becomes available */
|
||||
|
|
@ -7731,7 +7828,7 @@ _set_state_full (NMDevice *self,
|
|||
* we can't change states again from the state handler for a variety of
|
||||
* reasons.
|
||||
*/
|
||||
if (nm_device_is_available (self)) {
|
||||
if (nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
|
||||
_LOGD (LOGD_DEVICE, "device is available, will transition to DISCONNECTED");
|
||||
nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE);
|
||||
} else {
|
||||
|
|
@ -7762,7 +7859,8 @@ _set_state_full (NMDevice *self,
|
|||
}
|
||||
break;
|
||||
case NM_DEVICE_STATE_DISCONNECTED:
|
||||
if (priv->queued_act_request) {
|
||||
if ( priv->queued_act_request
|
||||
&& !priv->queued_act_request_is_waiting_for_carrier) {
|
||||
NMActRequest *queued_req;
|
||||
|
||||
queued_req = priv->queued_act_request;
|
||||
|
|
@ -8352,7 +8450,7 @@ dispose (GObject *object)
|
|||
priv->carrier_wait_id = 0;
|
||||
}
|
||||
|
||||
g_clear_object (&priv->queued_act_request);
|
||||
_clear_queued_act_request (priv);
|
||||
|
||||
platform = nm_platform_get ();
|
||||
g_signal_handlers_disconnect_by_func (platform, G_CALLBACK (device_ip_changed), self);
|
||||
|
|
|
|||
|
|
@ -86,10 +86,37 @@ G_BEGIN_DECLS
|
|||
|
||||
typedef enum NMActStageReturn NMActStageReturn;
|
||||
|
||||
/* These flags affect whether a connection is considered available on a device
|
||||
* (check_connection_available()). The flags should have the meaning of relaxing
|
||||
* a condition, so that adding a flag might make a connection available that would
|
||||
* not be available otherwise. Adding a flag should never make a connection
|
||||
* not available if it would be available otherwise. */
|
||||
typedef enum {
|
||||
NM_DEVICE_CHECK_CON_AVAILABLE_NONE = 0,
|
||||
|
||||
_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER = (1L << 0),
|
||||
_NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP = (1L << 1),
|
||||
NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER
|
||||
| _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP,
|
||||
|
||||
__NM_DEVICE_CHECK_CON_AVAILABLE_ALL,
|
||||
NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (((__NM_DEVICE_CHECK_CON_AVAILABLE_ALL - 1) << 1) - 1),
|
||||
} NMDeviceCheckConAvailableFlags;
|
||||
|
||||
struct _NMDevice {
|
||||
GObject parent;
|
||||
};
|
||||
|
||||
/* The flags have an relaxing meaning, that means, specifying more flags, can make
|
||||
* a device appear more available. It can never make a device less available. */
|
||||
typedef enum {
|
||||
NM_DEVICE_CHECK_DEV_AVAILABLE_NONE = 0,
|
||||
NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER = (1L << 0),
|
||||
|
||||
__NM_DEVICE_CHECK_DEV_AVAILABLE_ALL,
|
||||
NM_DEVICE_CHECK_DEV_AVAILABLE_ALL = (((__NM_DEVICE_CHECK_DEV_AVAILABLE_ALL - 1) << 1) - 1),
|
||||
} NMDeviceCheckDevAvailableFlags;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
|
|
@ -117,7 +144,7 @@ typedef struct {
|
|||
|
||||
guint32 (* get_generic_capabilities) (NMDevice *self);
|
||||
|
||||
gboolean (* is_available) (NMDevice *self);
|
||||
gboolean (* is_available) (NMDevice *self, NMDeviceCheckDevAvailableFlags flags);
|
||||
|
||||
gboolean (* get_enabled) (NMDevice *self);
|
||||
|
||||
|
|
@ -137,19 +164,18 @@ typedef struct {
|
|||
* including any live network information like scan lists. The connection
|
||||
* is checked against the object defined by @specific_object, if given.
|
||||
* Returns TRUE if the connection is available; FALSE if not.
|
||||
*
|
||||
* The passed @flags affect whether a connection is considered
|
||||
* available or not. Adding more flags, means the connection is
|
||||
* *more* available.
|
||||
*
|
||||
* Specifying @specific_object can only reduce the availability of a connection.
|
||||
*/
|
||||
gboolean (* check_connection_available) (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object);
|
||||
|
||||
/* Same as check_connection_available() but called if the connection
|
||||
* is not present in the activating-connections array during activation,
|
||||
* to give the device a chance to allow/deny the activation. This is a
|
||||
* hack only meant for hidden WiFi networks.
|
||||
*/
|
||||
gboolean (* check_connection_available_wifi_hidden) (NMDevice *self,
|
||||
NMConnection *connection);
|
||||
|
||||
gboolean (* complete_connection) (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
const char *specific_object,
|
||||
|
|
@ -268,7 +294,7 @@ NMConnection * nm_device_get_connection (NMDevice *dev);
|
|||
|
||||
void nm_device_removed (NMDevice *dev);
|
||||
|
||||
gboolean nm_device_is_available (NMDevice *dev);
|
||||
gboolean nm_device_is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags);
|
||||
gboolean nm_device_has_carrier (NMDevice *dev);
|
||||
|
||||
NMConnection * nm_device_generate_connection (NMDevice *self, NMDevice *master);
|
||||
|
|
@ -327,7 +353,8 @@ typedef enum {
|
|||
|
||||
/* Boundary value */
|
||||
__NM_UNMANAGED_LAST,
|
||||
NM_UNMANAGED_LAST = __NM_UNMANAGED_LAST - 1,
|
||||
NM_UNMANAGED_LAST = __NM_UNMANAGED_LAST - 1,
|
||||
NM_UNMANAGED_ALL = ((NM_UNMANAGED_LAST << 1) - 1),
|
||||
} NMUnmanagedFlags;
|
||||
|
||||
gboolean nm_device_get_managed (NMDevice *device);
|
||||
|
|
@ -371,9 +398,10 @@ gboolean nm_device_has_pending_action (NMDevice *device);
|
|||
GPtrArray *nm_device_get_available_connections (NMDevice *device,
|
||||
const char *specific_object);
|
||||
|
||||
gboolean nm_device_connection_is_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
gboolean allow_device_override);
|
||||
gboolean nm_device_check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object);
|
||||
|
||||
gboolean nm_device_notify_component_added (NMDevice *device, GObject *component);
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ get_generic_capabilities (NMDevice *device)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *device)
|
||||
is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
if (NM_DEVICE_GET_CLASS (device)->is_up)
|
||||
return NM_DEVICE_GET_CLASS (device)->is_up (device);
|
||||
|
|
@ -84,6 +84,7 @@ is_available (NMDevice *device)
|
|||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
/* Connections are always available because the carrier state is determined
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *device)
|
||||
is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device);
|
||||
|
||||
|
|
|
|||
|
|
@ -864,10 +864,10 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
|||
|
||||
|
||||
static gboolean
|
||||
_internal_check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object,
|
||||
gboolean ignore_ap_list)
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
|
||||
NMSettingWireless *s_wifi;
|
||||
|
|
@ -877,6 +877,9 @@ _internal_check_connection_available (NMDevice *device,
|
|||
s_wifi = nm_connection_get_setting_wireless (connection);
|
||||
g_return_val_if_fail (s_wifi, FALSE);
|
||||
|
||||
/* a connection that is available for a certain @specific_object, MUST
|
||||
* also be available in general (without @specific_object). */
|
||||
|
||||
if (specific_object) {
|
||||
NMAccessPoint *ap;
|
||||
|
||||
|
|
@ -892,8 +895,15 @@ _internal_check_connection_available (NMDevice *device,
|
|||
|| g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_AP) == 0)
|
||||
return TRUE;
|
||||
|
||||
/* Hidden SSIDs obviously don't always appear in the scan list either */
|
||||
if (nm_setting_wireless_get_hidden (s_wifi) || ignore_ap_list)
|
||||
/* Hidden SSIDs obviously don't always appear in the scan list either.
|
||||
*
|
||||
* For an explict user-activation-request, a connection is considered
|
||||
* available because for hidden Wi-Fi, clients didn't consistently
|
||||
* set the 'hidden' property to indicate hidden SSID networks. If
|
||||
* activating but the network isn't available let the device recheck
|
||||
* availability.
|
||||
*/
|
||||
if (nm_setting_wireless_get_hidden (s_wifi) || NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP))
|
||||
return TRUE;
|
||||
|
||||
/* check if its visible */
|
||||
|
|
@ -905,24 +915,6 @@ _internal_check_connection_available (NMDevice *device,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
const char *specific_object)
|
||||
{
|
||||
return _internal_check_connection_available (device, connection, specific_object, FALSE);
|
||||
}
|
||||
|
||||
/* FIXME: remove this function when we require the 'hidden' property to be
|
||||
* set before a hidden connection can be activated.
|
||||
*/
|
||||
static gboolean
|
||||
check_connection_available_wifi_hidden (NMDevice *device,
|
||||
NMConnection *connection)
|
||||
{
|
||||
return _internal_check_connection_available (device, connection, NULL, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* List of manufacturer default SSIDs that are often unchanged by users.
|
||||
*
|
||||
|
|
@ -1144,28 +1136,22 @@ complete_connection (NMDevice *device,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *device)
|
||||
is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
|
||||
guint32 state;
|
||||
|
||||
if (!priv->enabled) {
|
||||
_LOGD (LOGD_WIFI, "not available because not enabled");
|
||||
if (!priv->enabled)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!priv->sup_iface) {
|
||||
_LOGD (LOGD_WIFI, "not available because supplicant not running");
|
||||
if (!priv->sup_iface)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
state = nm_supplicant_interface_get_state (priv->sup_iface);
|
||||
if ( state < NM_SUPPLICANT_INTERFACE_STATE_READY
|
||||
|| state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) {
|
||||
_LOGD (LOGD_WIFI, "not available because supplicant interface not ready");
|
||||
|| state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -2170,7 +2156,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
|
|||
/* If the interface can now be activated because the supplicant is now
|
||||
* available, transition to DISCONNECTED.
|
||||
*/
|
||||
if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) {
|
||||
if ((devstate == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_DISCONNECTED,
|
||||
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE);
|
||||
|
|
@ -3341,7 +3327,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
|
|||
parent_class->is_available = is_available;
|
||||
parent_class->check_connection_compatible = check_connection_compatible;
|
||||
parent_class->check_connection_available = check_connection_available;
|
||||
parent_class->check_connection_available_wifi_hidden = check_connection_available_wifi_hidden;
|
||||
parent_class->complete_connection = complete_connection;
|
||||
parent_class->set_enabled = set_enabled;
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ update_availability (NMDeviceWimax *self, gboolean old_available)
|
|||
NMDeviceState state;
|
||||
gboolean new_available, changed = FALSE;
|
||||
|
||||
new_available = nm_device_is_available (device);
|
||||
new_available = nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
|
||||
if (new_available == old_available)
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -281,7 +281,7 @@ set_enabled (NMDevice *device, gboolean enabled)
|
|||
if (priv->enabled == enabled)
|
||||
return;
|
||||
|
||||
old_available = nm_device_is_available (NM_DEVICE (device));
|
||||
old_available = nm_device_is_available (NM_DEVICE (device), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
|
||||
priv->enabled = enabled;
|
||||
|
||||
nm_log_dbg (LOGD_WIMAX, "(%s): radio now %s",
|
||||
|
|
@ -334,12 +334,16 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
|||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
|
||||
const GSList *ns_iter = NULL;
|
||||
NMWimaxNsp *nsp;
|
||||
|
||||
/* a connection that is available for a certain @specific_object, MUST
|
||||
* also be available in general (without @specific_object). */
|
||||
|
||||
if (specific_object) {
|
||||
nsp = get_nsp_by_path (NM_DEVICE_WIMAX (device), specific_object);
|
||||
return nsp ? nm_wimax_nsp_check_compatible (nsp, connection) : FALSE;
|
||||
|
|
@ -484,30 +488,21 @@ can_auto_connect (NMDevice *device,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *device)
|
||||
is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device);
|
||||
const char *iface = nm_device_get_iface (device);
|
||||
|
||||
if (!priv->enabled) {
|
||||
nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled", iface);
|
||||
if (!priv->enabled)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!priv->wimaxd_enabled) {
|
||||
nm_log_dbg (LOGD_WIMAX, "(%s): not available because not enabled in wimaxd", iface);
|
||||
if (!priv->wimaxd_enabled)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nm_wimax_util_sdk_is_initialized ()) {
|
||||
nm_log_dbg (LOGD_WIMAX, "(%s): not available because WiMAX SDK not initialized", iface);
|
||||
if (!nm_wimax_util_sdk_is_initialized ())
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!priv->sdk) {
|
||||
nm_log_dbg (LOGD_WIMAX, "(%s): not available because not known to WiMAX SDK", iface);
|
||||
if (!priv->sdk)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return iwmxsdk_status_get (priv->sdk) >= WIMAX_API_DEVICE_STATUS_Ready;
|
||||
}
|
||||
|
|
@ -712,7 +707,7 @@ wmx_state_change_cb (struct wmxsdk *wmxsdk,
|
|||
return;
|
||||
|
||||
state = nm_device_get_state (NM_DEVICE (self));
|
||||
old_available = nm_device_is_available (NM_DEVICE (self));
|
||||
old_available = nm_device_is_available (NM_DEVICE (self), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
|
||||
|
||||
priv->status = new_status;
|
||||
if (priv->current_nsp)
|
||||
|
|
@ -1153,7 +1148,7 @@ static gboolean
|
|||
sdk_action_defer_cb (gpointer user_data)
|
||||
{
|
||||
NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data);
|
||||
gboolean old_available = nm_device_is_available (NM_DEVICE (self));
|
||||
gboolean old_available = nm_device_is_available (NM_DEVICE (self), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE);
|
||||
|
||||
NM_DEVICE_WIMAX_GET_PRIVATE (self)->sdk_action_defer_id = 0;
|
||||
update_availability (self, old_available);
|
||||
|
|
|
|||
|
|
@ -300,14 +300,14 @@ modem_state_cb (NMModem *modem,
|
|||
nm_device_recheck_available_connections (device);
|
||||
}
|
||||
|
||||
if ((dev_state >= NM_DEVICE_STATE_DISCONNECTED) && !nm_device_is_available (device)) {
|
||||
if ((dev_state >= NM_DEVICE_STATE_DISCONNECTED) && !nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_MODEM_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((dev_state == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device)) {
|
||||
if ((dev_state == NM_DEVICE_STATE_UNAVAILABLE) && nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_DISCONNECTED,
|
||||
NM_DEVICE_STATE_REASON_MODEM_AVAILABLE);
|
||||
|
|
@ -394,6 +394,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
|||
static gboolean
|
||||
check_connection_available (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
NMDeviceCheckConAvailableFlags flags,
|
||||
const char *specific_object)
|
||||
{
|
||||
NMDeviceModem *self = NM_DEVICE_MODEM (device);
|
||||
|
|
@ -583,24 +584,19 @@ set_enabled (NMDevice *device, gboolean enabled)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
is_available (NMDevice *device)
|
||||
is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
|
||||
{
|
||||
NMDeviceModem *self = NM_DEVICE_MODEM (device);
|
||||
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device);
|
||||
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (self);
|
||||
NMModemState modem_state;
|
||||
|
||||
if (!priv->rf_enabled) {
|
||||
_LOGD (LOGD_MB, "not available because WWAN airplane mode is on");
|
||||
if (!priv->rf_enabled)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert (priv->modem);
|
||||
modem_state = nm_modem_get_state (priv->modem);
|
||||
if (modem_state <= NM_MODEM_STATE_INITIALIZING) {
|
||||
_LOGD (LOGD_MB, "not available because modem is not ready (%s)",
|
||||
nm_modem_state_to_string (modem_state));
|
||||
if (modem_state <= NM_MODEM_STATE_INITIALIZING)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2538,7 +2538,7 @@ ensure_master_active_connection (NMManager *self,
|
|||
if (!is_compatible_with_slave (candidate, connection))
|
||||
continue;
|
||||
|
||||
if (nm_device_connection_is_available (master_device, candidate, TRUE)) {
|
||||
if (nm_device_check_connection_available (master_device, candidate, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) {
|
||||
master_ac = nm_manager_activate_connection (self,
|
||||
candidate,
|
||||
NULL,
|
||||
|
|
@ -2579,7 +2579,7 @@ ensure_master_active_connection (NMManager *self,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!nm_device_connection_is_available (candidate, master_connection, TRUE))
|
||||
if (!nm_device_check_connection_available (candidate, master_connection, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL))
|
||||
continue;
|
||||
|
||||
found_device = TRUE;
|
||||
|
|
@ -2696,7 +2696,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
|
|||
* in the UNAVAILABLE state here. To ensure it can be activated
|
||||
* immediately, we transition it to DISCONNECTED.
|
||||
*/
|
||||
if ( nm_device_is_available (device)
|
||||
if ( nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)
|
||||
&& (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_DISCONNECTED,
|
||||
|
|
@ -2729,7 +2729,7 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
|
|||
}
|
||||
|
||||
/* Final connection must be available on device */
|
||||
if (!nm_device_connection_is_available (device, connection, TRUE)) {
|
||||
if (!nm_device_check_connection_available (device, connection, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST, NULL)) {
|
||||
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_CONNECTION,
|
||||
"Connection '%s' is not available on the device %s at this time.",
|
||||
nm_connection_get_id (connection), nm_device_get_iface (device));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue