mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-24 17:10:08 +01:00
core: move carrier-detect NMDeviceState handling into NMDevice
Move some duplicated carrier-handling code into NMDevice (which can introspect itself to see if it's a subclass that has carrier). The "mostly ignore carrier" special handling for bridges and bonds is now also handled as part of the NMDevice-level carrier handling. https://bugzilla.gnome.org/show_bug.cgi?id=688284
This commit is contained in:
parent
cc7e5cc591
commit
fe307dbd3e
7 changed files with 127 additions and 232 deletions
|
|
@ -608,7 +608,6 @@ static void
|
|||
set_carrier (NMDeviceAdsl *self, const gboolean carrier)
|
||||
{
|
||||
NMDeviceAdslPrivate *priv;
|
||||
NMDeviceState state;
|
||||
|
||||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
|
|
@ -619,20 +618,6 @@ set_carrier (NMDeviceAdsl *self, const gboolean carrier)
|
|||
|
||||
priv->carrier = carrier;
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_ADSL_CARRIER);
|
||||
|
||||
state = nm_device_get_state (NM_DEVICE (self));
|
||||
nm_log_info (LOGD_HW, "(%s): carrier now %s (device state %d)",
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
carrier ? "ON" : "OFF",
|
||||
state);
|
||||
|
||||
if (state == NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
if (priv->carrier)
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
if (!priv->carrier)
|
||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
|||
|
|
@ -80,23 +80,6 @@ nm_bond_error_quark (void)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier)
|
||||
{
|
||||
/* Carrier can't be used to signal availability of the bond master because
|
||||
* the bond's carrier follows the slaves' carriers. So carrier gets
|
||||
* ignored when determining whether or not the device can be activated.
|
||||
*
|
||||
* Second, just because all slaves have been removed or have lost carrier
|
||||
* does not mean the master should be deactivated. This could be due to
|
||||
* user addition/removal of slaves, and is also normal operation with some
|
||||
* failover modes.
|
||||
*
|
||||
* For these reasons, carrier changes are effectively ignored by overriding
|
||||
* the parent class' carrier handling and doing nothing.
|
||||
*/
|
||||
}
|
||||
|
||||
static void
|
||||
update_hw_address (NMDevice *dev)
|
||||
{
|
||||
|
|
@ -463,7 +446,6 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
|
|||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
|
||||
NMDeviceWiredClass *wired_class = NM_DEVICE_WIRED_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (NMDeviceBondPrivate));
|
||||
|
||||
|
|
@ -487,8 +469,6 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
|
|||
parent_class->enslave_slave = enslave_slave;
|
||||
parent_class->release_slave = release_slave;
|
||||
|
||||
wired_class->carrier_action = carrier_action;
|
||||
|
||||
/* properties */
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_HW_ADDRESS,
|
||||
|
|
|
|||
|
|
@ -80,20 +80,6 @@ nm_bridge_error_quark (void)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier)
|
||||
{
|
||||
/* Bridge carrier state follows IFF_UP with no ports, and port carrier
|
||||
* states when ports are added. Thus carrier isn't useful when deciding
|
||||
* to auto-activate the bridge master. Also, like bond masters, when the
|
||||
* carrier state changes due to slave changes, we shouldn't deactivate the
|
||||
* bridge since the user may be reconfiguring ports.
|
||||
*
|
||||
* For these reasons, carrier changes are effectively ignored by overriding
|
||||
* the parent class' carrier handling and doing nothing.
|
||||
*/
|
||||
}
|
||||
|
||||
static void
|
||||
update_hw_address (NMDevice *dev)
|
||||
{
|
||||
|
|
@ -516,7 +502,6 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
|
|||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
|
||||
NMDeviceWiredClass *wired_class = NM_DEVICE_WIRED_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (NMDeviceBridgePrivate));
|
||||
|
||||
|
|
@ -540,8 +525,6 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
|
|||
parent_class->enslave_slave = enslave_slave;
|
||||
parent_class->release_slave = release_slave;
|
||||
|
||||
wired_class->carrier_action = carrier_action;
|
||||
|
||||
/* properties */
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_HW_ADDRESS,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ typedef struct {
|
|||
NMNetlinkMonitor *monitor;
|
||||
gulong link_connected_id;
|
||||
gulong link_disconnected_id;
|
||||
guint carrier_action_defer_id;
|
||||
} NMDeviceVlanPrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -83,8 +82,7 @@ enum {
|
|||
|
||||
static void
|
||||
set_carrier (NMDeviceVlan *self,
|
||||
const gboolean carrier,
|
||||
const gboolean defer_action);
|
||||
const gboolean carrier);
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
|
|
@ -147,7 +145,7 @@ hw_bring_up (NMDevice *dev, gboolean *no_firmware)
|
|||
i = 20;
|
||||
while (i-- > 0) {
|
||||
carrier = get_carrier_sync (NM_DEVICE_VLAN (dev));
|
||||
set_carrier (NM_DEVICE_VLAN (dev), carrier, carrier ? FALSE : TRUE);
|
||||
set_carrier (NM_DEVICE_VLAN (dev), carrier);
|
||||
if (carrier)
|
||||
break;
|
||||
g_usleep (100);
|
||||
|
|
@ -441,66 +439,17 @@ connection_match_config (NMDevice *self, const GSList *connections)
|
|||
|
||||
/******************************************************************/
|
||||
|
||||
static void
|
||||
carrier_action_defer_clear (NMDeviceVlan *self)
|
||||
{
|
||||
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
|
||||
|
||||
if (priv->carrier_action_defer_id) {
|
||||
g_source_remove (priv->carrier_action_defer_id);
|
||||
priv->carrier_action_defer_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
carrier_action_defer_cb (gpointer user_data)
|
||||
{
|
||||
NMDeviceVlan *self = NM_DEVICE_VLAN (user_data);
|
||||
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
|
||||
NMDeviceState state;
|
||||
|
||||
priv->carrier_action_defer_id = 0;
|
||||
|
||||
state = nm_device_get_state (NM_DEVICE (self));
|
||||
if (state == NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
if (priv->carrier)
|
||||
nm_device_queue_state (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
if (!priv->carrier)
|
||||
nm_device_queue_state (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_carrier (NMDeviceVlan *self,
|
||||
const gboolean carrier,
|
||||
const gboolean defer_action)
|
||||
const gboolean carrier)
|
||||
{
|
||||
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
|
||||
NMDeviceState state;
|
||||
|
||||
if (priv->carrier == carrier)
|
||||
return;
|
||||
|
||||
/* Clear any previous deferred action */
|
||||
carrier_action_defer_clear (self);
|
||||
|
||||
priv->carrier = carrier;
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_VLAN_CARRIER);
|
||||
|
||||
state = nm_device_get_state (NM_DEVICE (self));
|
||||
nm_log_info (LOGD_HW | LOGD_VLAN,
|
||||
"(%s): carrier now %s (device state %d%s)",
|
||||
nm_device_get_iface (NM_DEVICE (self)),
|
||||
carrier ? "ON" : "OFF",
|
||||
state,
|
||||
defer_action ? ", deferring action for 4 seconds" : "");
|
||||
|
||||
if (defer_action)
|
||||
priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self);
|
||||
else
|
||||
carrier_action_defer_cb (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -508,27 +457,15 @@ carrier_on (NMNetlinkMonitor *monitor, int idx, NMDevice *device)
|
|||
{
|
||||
/* Make sure signal is for us */
|
||||
if (idx == nm_device_get_ifindex (device))
|
||||
set_carrier (NM_DEVICE_VLAN (device), TRUE, FALSE);
|
||||
set_carrier (NM_DEVICE_VLAN (device), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
carrier_off (NMNetlinkMonitor *monitor, int idx, NMDevice *device)
|
||||
{
|
||||
NMDeviceState state;
|
||||
gboolean defer = FALSE;
|
||||
|
||||
/* Make sure signal is for us */
|
||||
if (idx == nm_device_get_ifindex (device)) {
|
||||
/* Defer carrier-off event actions while connected by a few seconds
|
||||
* so that tripping over a cable, power-cycling a switch, or breaking
|
||||
* off the RJ45 locking tab isn't so catastrophic.
|
||||
*/
|
||||
state = nm_device_get_state (device);
|
||||
if (state > NM_DEVICE_STATE_DISCONNECTED)
|
||||
defer = TRUE;
|
||||
|
||||
set_carrier (NM_DEVICE_VLAN (device), FALSE, defer);
|
||||
}
|
||||
if (idx == nm_device_get_ifindex (device))
|
||||
set_carrier (NM_DEVICE_VLAN (device), FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -704,7 +641,6 @@ dispose (GObject *object)
|
|||
g_signal_handler_disconnect (priv->monitor, priv->link_connected_id);
|
||||
if (priv->link_disconnected_id)
|
||||
g_signal_handler_disconnect (priv->monitor, priv->link_disconnected_id);
|
||||
carrier_action_defer_clear (self);
|
||||
|
||||
g_object_unref (priv->monitor);
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ typedef struct {
|
|||
NMNetlinkMonitor * monitor;
|
||||
gulong link_connected_id;
|
||||
gulong link_disconnected_id;
|
||||
guint carrier_action_defer_id;
|
||||
|
||||
} NMDeviceWiredPrivate;
|
||||
|
||||
|
|
@ -120,67 +119,17 @@ set_speed (NMDeviceWired *self, const guint32 speed)
|
|||
speed);
|
||||
}
|
||||
|
||||
static void
|
||||
carrier_action_defer_clear (NMDeviceWired *self)
|
||||
{
|
||||
NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
|
||||
|
||||
if (priv->carrier_action_defer_id) {
|
||||
g_source_remove (priv->carrier_action_defer_id);
|
||||
priv->carrier_action_defer_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
carrier_action (NMDeviceWired *self, NMDeviceState state, gboolean carrier)
|
||||
{
|
||||
NMDevice *device = NM_DEVICE (self);
|
||||
|
||||
if (state == NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
if (carrier)
|
||||
nm_device_queue_state (device, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
else {
|
||||
/* clear any queued state changes if they wouldn't be valid when the
|
||||
* carrier is off.
|
||||
*/
|
||||
if (nm_device_queued_state_peek (device) >= NM_DEVICE_STATE_DISCONNECTED)
|
||||
nm_device_queued_state_clear (device);
|
||||
}
|
||||
} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
if (!carrier && !nm_device_get_enslaved (device))
|
||||
nm_device_queue_state (device, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
carrier_action_defer_cb (gpointer user_data)
|
||||
{
|
||||
NMDeviceWired *self = NM_DEVICE_WIRED (user_data);
|
||||
NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
|
||||
|
||||
priv->carrier_action_defer_id = 0;
|
||||
NM_DEVICE_WIRED_GET_CLASS (self)->carrier_action (self,
|
||||
nm_device_get_state (NM_DEVICE (self)),
|
||||
priv->carrier);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
set_carrier (NMDeviceWired *self,
|
||||
const gboolean carrier,
|
||||
const gboolean defer_action)
|
||||
gboolean carrier)
|
||||
{
|
||||
NMDeviceWiredPrivate *priv = NM_DEVICE_WIRED_GET_PRIVATE (self);
|
||||
NMDevice *device = NM_DEVICE (self);
|
||||
NMDeviceState state;
|
||||
NMDeviceWiredPrivate *priv;
|
||||
guint32 caps;
|
||||
|
||||
if (priv->carrier == carrier)
|
||||
return;
|
||||
|
||||
/* Clear any previous deferred action */
|
||||
carrier_action_defer_clear (self);
|
||||
|
||||
/* Warn if we try to set carrier down on a device that
|
||||
* doesn't support carrier detect. These devices assume
|
||||
* the carrier is always up.
|
||||
|
|
@ -189,32 +138,7 @@ set_carrier (NMDeviceWired *self,
|
|||
g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT);
|
||||
|
||||
priv->carrier = carrier;
|
||||
|
||||
state = nm_device_get_state (device);
|
||||
if (state >= NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (device),
|
||||
"(%s): carrier now %s (device state %d%s)",
|
||||
nm_device_get_iface (device),
|
||||
carrier ? "ON" : "OFF",
|
||||
state,
|
||||
defer_action ? ", deferring action for 4 seconds" : "");
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (self), "carrier");
|
||||
|
||||
/* Retry IP configuration for master devices now that the carrier is on */
|
||||
if (nm_device_is_master (device) && priv->carrier) {
|
||||
if (nm_device_activate_ip4_state_in_wait (device))
|
||||
nm_device_activate_stage3_ip4_start (device);
|
||||
|
||||
if (nm_device_activate_ip6_state_in_wait (device))
|
||||
nm_device_activate_stage3_ip6_start (device);
|
||||
}
|
||||
|
||||
if (defer_action)
|
||||
priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self);
|
||||
else
|
||||
carrier_action_defer_cb (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -224,14 +148,10 @@ carrier_on (NMNetlinkMonitor *monitor,
|
|||
{
|
||||
NMDevice *device = NM_DEVICE (user_data);
|
||||
NMDeviceWired *self = NM_DEVICE_WIRED (device);
|
||||
guint32 caps;
|
||||
|
||||
/* Make sure signal is for us */
|
||||
if (idx == nm_device_get_ifindex (device)) {
|
||||
caps = nm_device_get_capabilities (device);
|
||||
g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT);
|
||||
|
||||
set_carrier (self, TRUE, FALSE);
|
||||
set_carrier (self, TRUE);
|
||||
set_speed (self, ethtool_get_speed (self));
|
||||
}
|
||||
}
|
||||
|
|
@ -243,26 +163,10 @@ carrier_off (NMNetlinkMonitor *monitor,
|
|||
{
|
||||
NMDevice *device = NM_DEVICE (user_data);
|
||||
NMDeviceWired *self = NM_DEVICE_WIRED (device);
|
||||
guint32 caps;
|
||||
|
||||
/* Make sure signal is for us */
|
||||
if (idx == nm_device_get_ifindex (device)) {
|
||||
NMDeviceState state;
|
||||
gboolean defer = FALSE;
|
||||
|
||||
caps = nm_device_get_capabilities (device);
|
||||
g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT);
|
||||
|
||||
/* Defer carrier-off event actions while connected by a few seconds
|
||||
* so that tripping over a cable, power-cycling a switch, or breaking
|
||||
* off the RJ45 locking tab isn't so catastrophic.
|
||||
*/
|
||||
state = nm_device_get_state (device);
|
||||
if (state > NM_DEVICE_STATE_DISCONNECTED)
|
||||
defer = TRUE;
|
||||
|
||||
set_carrier (self, FALSE, defer);
|
||||
}
|
||||
if (idx == nm_device_get_ifindex (device))
|
||||
set_carrier (self, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -362,7 +266,7 @@ hw_bring_up (NMDevice *dev, gboolean *no_firmware)
|
|||
caps = nm_device_get_capabilities (dev);
|
||||
if (caps & NM_DEVICE_CAP_CARRIER_DETECT) {
|
||||
carrier = get_carrier_sync (NM_DEVICE_WIRED (dev));
|
||||
set_carrier (NM_DEVICE_WIRED (dev), carrier, carrier ? FALSE : TRUE);
|
||||
set_carrier (NM_DEVICE_WIRED (dev), carrier);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
@ -458,8 +362,6 @@ dispose (GObject *object)
|
|||
priv->link_disconnected_id = 0;
|
||||
}
|
||||
|
||||
carrier_action_defer_clear (self);
|
||||
|
||||
if (priv->monitor) {
|
||||
g_object_unref (priv->monitor);
|
||||
priv->monitor = NULL;
|
||||
|
|
@ -473,7 +375,6 @@ nm_device_wired_class_init (NMDeviceWiredClass *klass)
|
|||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass);
|
||||
NMDeviceWiredClass *wired_class = NM_DEVICE_WIRED_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (object_class, sizeof (NMDeviceWiredPrivate));
|
||||
|
||||
|
|
@ -487,8 +388,6 @@ nm_device_wired_class_init (NMDeviceWiredClass *klass)
|
|||
parent_class->connection_match_config = connection_match_config;
|
||||
parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
|
||||
parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start;
|
||||
|
||||
wired_class->carrier_action = carrier_action;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -42,9 +42,6 @@ typedef struct {
|
|||
typedef struct {
|
||||
NMDeviceClass parent;
|
||||
|
||||
void (*carrier_action) (NMDeviceWired *self,
|
||||
NMDeviceState state,
|
||||
gboolean carrier);
|
||||
} NMDeviceWiredClass;
|
||||
|
||||
GType nm_device_wired_get_type (void);
|
||||
|
|
|
|||
115
src/nm-device.c
115
src/nm-device.c
|
|
@ -262,6 +262,10 @@ typedef struct {
|
|||
guint cp_loaded_id;
|
||||
guint cp_removed_id;
|
||||
guint cp_updated_id;
|
||||
|
||||
/* Deferred carrier handling */
|
||||
guint carrier_action_defer_id;
|
||||
|
||||
} NMDevicePrivate;
|
||||
|
||||
static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReason reason);
|
||||
|
|
@ -294,6 +298,9 @@ static void cp_connection_updated (NMConnectionProvider *cp, NMConnection *conne
|
|||
|
||||
static const char *state_to_string (NMDeviceState state);
|
||||
|
||||
static void carrier_changed (GObject *object, GParamSpec *param, gpointer user_data);
|
||||
static void carrier_action_defer_clear (NMDevice *self);
|
||||
|
||||
static void
|
||||
nm_device_init (NMDevice *self)
|
||||
{
|
||||
|
|
@ -463,6 +470,9 @@ constructor (GType type,
|
|||
update_accept_ra_save (dev);
|
||||
update_ip6_privacy_save (dev);
|
||||
|
||||
if (g_object_class_find_property (G_OBJECT_GET_CLASS (dev), "carrier"))
|
||||
g_signal_connect (dev, "notify::carrier", G_CALLBACK (carrier_changed), NULL);
|
||||
|
||||
priv->initialized = TRUE;
|
||||
return object;
|
||||
|
||||
|
|
@ -1151,6 +1161,109 @@ nm_device_get_act_request (NMDevice *self)
|
|||
return NM_DEVICE_GET_PRIVATE (self)->act_request;
|
||||
}
|
||||
|
||||
static void
|
||||
carrier_action_defer_clear (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->carrier_action_defer_id) {
|
||||
g_source_remove (priv->carrier_action_defer_id);
|
||||
priv->carrier_action_defer_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
carrier_action_defer_cb (gpointer user_data)
|
||||
{
|
||||
NMDevice *self = NM_DEVICE (user_data);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMDeviceState state;
|
||||
|
||||
priv->carrier_action_defer_id = 0;
|
||||
|
||||
/* We know that carrier is FALSE */
|
||||
|
||||
state = nm_device_get_state (self);
|
||||
if (state >= NM_DEVICE_STATE_DISCONNECTED)
|
||||
nm_device_queue_state (self, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
carrier_changed (GObject *object, GParamSpec *param, gpointer user_data)
|
||||
{
|
||||
NMDevice *self = NM_DEVICE (object);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
gboolean carrier, defer_action = FALSE;
|
||||
NMDeviceState state;
|
||||
|
||||
/* Clear any previous deferred action */
|
||||
carrier_action_defer_clear (self);
|
||||
|
||||
state = nm_device_get_state (self);
|
||||
if (state < NM_DEVICE_STATE_UNAVAILABLE)
|
||||
return;
|
||||
|
||||
g_object_get (object, "carrier", &carrier, NULL);
|
||||
|
||||
if (nm_device_is_master (self)) {
|
||||
/* Bridge/bond carrier does not affect its own activation, but
|
||||
* when carrier comes on, if there are slaves waiting, it will
|
||||
* restart them.
|
||||
*/
|
||||
if (!carrier)
|
||||
return;
|
||||
|
||||
if (!nm_device_activate_ip4_state_in_wait (self) &&
|
||||
!nm_device_activate_ip6_state_in_wait (self))
|
||||
return;
|
||||
} else if (nm_device_get_enslaved (self) && !carrier) {
|
||||
/* Slaves don't deactivate when they lose carrier; for bonds
|
||||
* in particular that would be actively counterproductive.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->act_request && !carrier)
|
||||
defer_action = TRUE;
|
||||
|
||||
nm_log_info (LOGD_HW | LOGD_DEVICE, "(%s): carrier now %s (device state %d%s)",
|
||||
nm_device_get_iface (self),
|
||||
carrier ? "ON" : "OFF",
|
||||
state,
|
||||
defer_action ? ", deferring action for 4 seconds" : "");
|
||||
|
||||
if (nm_device_is_master (self)) {
|
||||
if (nm_device_activate_ip4_state_in_wait (self))
|
||||
nm_device_activate_stage3_ip4_start (self);
|
||||
|
||||
if (nm_device_activate_ip6_state_in_wait (self))
|
||||
nm_device_activate_stage3_ip6_start (self);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == NM_DEVICE_STATE_UNAVAILABLE) {
|
||||
if (carrier)
|
||||
nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
else {
|
||||
/* clear any queued state changes if they wouldn't be valid when the
|
||||
* carrier is off.
|
||||
*/
|
||||
if (nm_device_queued_state_peek (self) >= NM_DEVICE_STATE_DISCONNECTED)
|
||||
nm_device_queued_state_clear (self);
|
||||
}
|
||||
} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
|
||||
if (!carrier) {
|
||||
if (defer_action)
|
||||
priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self);
|
||||
else
|
||||
nm_device_queue_state (self, NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NMConnection *
|
||||
nm_device_get_connection (NMDevice *self)
|
||||
{
|
||||
|
|
@ -4328,6 +4441,8 @@ dispose (GObject *object)
|
|||
priv->cp_updated_id = 0;
|
||||
}
|
||||
|
||||
carrier_action_defer_clear (self);
|
||||
|
||||
g_hash_table_unref (priv->available_connections);
|
||||
|
||||
activation_source_clear (self, TRUE, AF_INET);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue