mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-21 18:24:49 +00:00
core: change the rules for ignore-carrier
The previous ignore-carrier rules did not work well with dynamic IP (dhcp/slaac) connections. Change the rule so that only static IP connections can be activated when carrier is not present (but both static and dynamic connections will remain up when carrier is lost).
This commit is contained in:
parent
841ca9bb84
commit
17e91fd46a
|
@ -12,5 +12,5 @@
|
|||
no-auto-default=*
|
||||
|
||||
# Ignore the carrier (cable plugged in) state when attempting to
|
||||
# activate connections.
|
||||
# activate static-IP connections.
|
||||
ignore-carrier=*
|
||||
|
|
|
@ -147,27 +147,32 @@ Copyright (C) 2010 - 2013 Red Hat, Inc.
|
|||
<term><varname>ignore-carrier</varname></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Comma-separated list of devices for which
|
||||
NetworkManager will ignore the carrier (cable plugged in)
|
||||
state. Normally, for device types that support
|
||||
carrier-detect, such as Ethernet and InfiniBand,
|
||||
NetworkManager will only allow a connection to be activated on
|
||||
the device if carrier is present (ie, a cable is plugged in).
|
||||
List a device here to allow attempting to activate a
|
||||
connection anyways. May have the special value
|
||||
<literal>*</literal> to apply to all devices.
|
||||
Comma-separated list of devices for which NetworkManager
|
||||
will (partially) ignore the carrier state. Normally, for
|
||||
device types that support carrier-detect, such as Ethernet
|
||||
and InfiniBand, NetworkManager will only allow a
|
||||
connection to be activated on the device if carrier is
|
||||
present (ie, a cable is plugged in), and it will
|
||||
deactivate the device if carrier drops for more than a few
|
||||
seconds.
|
||||
</para>
|
||||
<para>
|
||||
Listing a device here will allow activating connections on
|
||||
that device even when it does not have carrier, provided
|
||||
that the connection uses only statically-configured IP
|
||||
addresses. Additionally, it will allow any active
|
||||
connection (whether static or dynamic) to remain active on
|
||||
the device when carrier is lost.
|
||||
</para>
|
||||
<para>
|
||||
May have the special value <literal>*</literal> to apply
|
||||
to all devices.
|
||||
</para>
|
||||
<para>
|
||||
Note that the "carrier" property of NMDevices and device D-Bus
|
||||
interfaces will still reflect the actual device state; it's just
|
||||
that NetworkManager will not make use of that information.
|
||||
</para>
|
||||
<para>
|
||||
You should probably not set this to apply to devices where you are
|
||||
doing automatic IP config, since they will eventually fail if there
|
||||
is no actual network connectivity, and NetworkManager won't retry
|
||||
them right away when carrier comes back up (since it's ignoring it).
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
|
@ -983,14 +983,63 @@ nm_device_release_one_slave (NMDevice *dev, NMDevice *slave, gboolean failed)
|
|||
return success;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
connection_is_static (NMConnection *connection)
|
||||
{
|
||||
NMSettingIP4Config *ip4;
|
||||
NMSettingIP6Config *ip6;
|
||||
const char *method;
|
||||
|
||||
ip4 = nm_connection_get_setting_ip4_config (connection);
|
||||
if (ip4) {
|
||||
method = nm_setting_ip4_config_get_method (ip4);
|
||||
if ( g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) != 0
|
||||
&& g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
if (ip6) {
|
||||
method = nm_setting_ip6_config_get_method (ip6);
|
||||
if ( g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) != 0
|
||||
&& g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
has_static_connection (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
const GSList *connections, *iter;
|
||||
|
||||
connections = nm_connection_provider_get_connections (priv->con_provider);
|
||||
for (iter = connections; iter; iter = iter->next) {
|
||||
NMConnection *connection = iter->data;
|
||||
|
||||
if ( nm_device_check_connection_compatible (self, connection, NULL)
|
||||
&& connection_is_static (connection))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
carrier_changed (NMDevice *device, gboolean carrier)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
|
||||
if (priv->ignore_carrier || !nm_device_get_managed (device))
|
||||
if (!nm_device_get_managed (device))
|
||||
return;
|
||||
|
||||
if (priv->ignore_carrier) {
|
||||
/* Ignore all carrier-off, and ignore carrier-on on connected devices */
|
||||
if (!carrier || priv->state > NM_DEVICE_STATE_DISCONNECTED)
|
||||
return;
|
||||
}
|
||||
|
||||
if (nm_device_is_master (device)) {
|
||||
/* Bridge/bond carrier does not affect its own activation, but
|
||||
* when carrier comes on, if there are slaves waiting, it will
|
||||
|
@ -1368,9 +1417,32 @@ is_available (NMDevice *device)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
|
||||
|
||||
return priv->carrier || priv->ignore_carrier;
|
||||
if (!priv->carrier) {
|
||||
if (priv->ignore_carrier && has_static_connection (device))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_is_available:
|
||||
* @self: the #NMDevice
|
||||
*
|
||||
* Checks if @self would currently be capable of activating a
|
||||
* connection. In particular, it checks that the device is ready (eg,
|
||||
* is not missing firmware), that it has carrier (if necessary), and
|
||||
* that any necessary external software (eg, ModemManager,
|
||||
* wpa_supplicant) is available.
|
||||
*
|
||||
* @self can only be in a state higher than
|
||||
* %NM_DEVICE_STATE_UNAVAILABLE when nm_device_is_available() returns
|
||||
* %TRUE. (But note that it can still be %NM_DEVICE_STATE_UNMANAGED
|
||||
* when it is available.)
|
||||
*
|
||||
* Returns: %TRUE or %FALSE
|
||||
*/
|
||||
gboolean
|
||||
nm_device_is_available (NMDevice *self)
|
||||
{
|
||||
|
@ -1382,17 +1454,54 @@ nm_device_is_available (NMDevice *self)
|
|||
return NM_DEVICE_GET_CLASS (self)->is_available (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_can_activate:
|
||||
* @self: the #NMDevice
|
||||
* @connection: (allow-none) an #NMConnection, or %NULL
|
||||
*
|
||||
* Checks if @self can currently activate @connection. In particular,
|
||||
* this requires that @self is available (per
|
||||
* nm_device_is_available()); that it is either managed or able to
|
||||
* become managed; and that it is able to activate @connection in its
|
||||
* current state (eg, if @connection requires carrier, then @self has
|
||||
* carrier).
|
||||
*
|
||||
* If @connection is %NULL, this just checks that @self could
|
||||
* theoretically activate *some* connection.
|
||||
*
|
||||
* Returns: %TRUE or %FALSE
|
||||
*/
|
||||
gboolean
|
||||
nm_device_can_activate (NMDevice *self)
|
||||
nm_device_can_activate (NMDevice *self, NMConnection *connection)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->manager_managed)
|
||||
return FALSE;
|
||||
if (!priv->default_unmanaged && priv->state < NM_DEVICE_STATE_DISCONNECTED)
|
||||
|
||||
if ( connection
|
||||
&& !nm_device_check_connection_compatible (self, connection, NULL))
|
||||
return FALSE;
|
||||
|
||||
return nm_device_is_available (self);
|
||||
if (priv->default_unmanaged) {
|
||||
if (!nm_device_is_available (self))
|
||||
return FALSE;
|
||||
} else if (priv->state < NM_DEVICE_STATE_DISCONNECTED) {
|
||||
if (priv->state != NM_DEVICE_STATE_UNAVAILABLE || priv->carrier || !priv->ignore_carrier)
|
||||
return FALSE;
|
||||
|
||||
/* @self is UNAVAILABLE because it doesn't have carrier, but
|
||||
* ignore-carrier is set, so we might be able to ignore that.
|
||||
*/
|
||||
if (connection && connection_is_static (connection))
|
||||
return TRUE;
|
||||
else if (!connection && has_static_connection (self))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -1471,7 +1580,7 @@ can_auto_connect (NMDevice *device,
|
|||
if (!nm_setting_connection_get_autoconnect (s_con))
|
||||
return FALSE;
|
||||
|
||||
return nm_device_check_connection_compatible (device, connection, NULL);
|
||||
return nm_device_can_activate (device, connection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4105,7 +4214,7 @@ nm_device_activate (NMDevice *self, NMActRequest *req)
|
|||
nm_connection_get_id (connection));
|
||||
|
||||
if (priv->state < NM_DEVICE_STATE_DISCONNECTED) {
|
||||
g_return_if_fail (nm_device_can_activate (self));
|
||||
g_return_if_fail (nm_device_can_activate (self, connection));
|
||||
|
||||
if (priv->state == NM_DEVICE_STATE_UNMANAGED) {
|
||||
nm_device_state_changed (self,
|
||||
|
|
|
@ -235,8 +235,9 @@ void nm_device_slave_notify_enslaved (NMDevice *dev,
|
|||
NMActRequest * nm_device_get_act_request (NMDevice *dev);
|
||||
NMConnection * nm_device_get_connection (NMDevice *dev);
|
||||
|
||||
gboolean nm_device_is_available (NMDevice *dev);
|
||||
gboolean nm_device_can_activate (NMDevice *dev);
|
||||
gboolean nm_device_is_available (NMDevice *dev);
|
||||
gboolean nm_device_can_activate (NMDevice *dev,
|
||||
NMConnection *connection);
|
||||
|
||||
gboolean nm_device_has_carrier (NMDevice *dev);
|
||||
gboolean nm_device_ignore_carrier (NMDevice *dev);
|
||||
|
|
|
@ -2008,7 +2008,7 @@ add_device (NMManager *self, NMDevice *device)
|
|||
system_create_virtual_devices (self);
|
||||
|
||||
/* If the device has a connection it can assume, do that now */
|
||||
if (existing && nm_device_can_activate (device)) {
|
||||
if (existing && nm_device_can_activate (device, existing)) {
|
||||
NMActiveConnection *ac;
|
||||
GError *error = NULL;
|
||||
|
||||
|
@ -2950,7 +2950,7 @@ nm_manager_activate_connection (NMManager *manager,
|
|||
}
|
||||
}
|
||||
|
||||
if (!nm_device_can_activate (device)) {
|
||||
if (!nm_device_can_activate (device, connection)) {
|
||||
g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNMANAGED_DEVICE,
|
||||
"Device not managed by NetworkManager or unavailable");
|
||||
return NULL;
|
||||
|
|
|
@ -1119,7 +1119,7 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device, guint delay_seconds
|
|||
if (nm_manager_get_state (policy->manager) == NM_STATE_ASLEEP)
|
||||
return;
|
||||
|
||||
if (!nm_device_can_activate (device))
|
||||
if (!nm_device_can_activate (device, NULL))
|
||||
return;
|
||||
|
||||
if (!nm_device_get_enabled (device))
|
||||
|
|
Loading…
Reference in a new issue