mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-08 07:48:10 +02:00
wired: defer carrier-off events while connected by a few seconds
Don't immediately tear down an active wired connection when the carrier flips to off, but wait a few seconds for it to come back before breaking the user's network.
This commit is contained in:
parent
4f6eef9e77
commit
963d055abf
1 changed files with 68 additions and 11 deletions
|
|
@ -110,6 +110,7 @@ typedef struct {
|
||||||
NMNetlinkMonitor * monitor;
|
NMNetlinkMonitor * monitor;
|
||||||
gulong link_connected_id;
|
gulong link_connected_id;
|
||||||
gulong link_disconnected_id;
|
gulong link_disconnected_id;
|
||||||
|
guint carrier_action_defer_id;
|
||||||
|
|
||||||
Supplicant supplicant;
|
Supplicant supplicant;
|
||||||
guint supplicant_timeout_id;
|
guint supplicant_timeout_id;
|
||||||
|
|
@ -174,7 +175,41 @@ nm_ethernet_error_get_type (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_carrier (NMDeviceEthernet *self, const gboolean carrier)
|
carrier_action_defer_clear (NMDeviceEthernet *self)
|
||||||
|
{
|
||||||
|
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_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)
|
||||||
|
{
|
||||||
|
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
|
||||||
|
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
|
||||||
|
NMDeviceState state;
|
||||||
|
|
||||||
|
priv->carrier_action_defer_id = 0;
|
||||||
|
|
||||||
|
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_carrier (NMDeviceEthernet *self,
|
||||||
|
const gboolean carrier,
|
||||||
|
const gboolean defer_action)
|
||||||
{
|
{
|
||||||
NMDeviceEthernetPrivate *priv;
|
NMDeviceEthernetPrivate *priv;
|
||||||
NMDeviceState state;
|
NMDeviceState state;
|
||||||
|
|
@ -185,18 +220,23 @@ set_carrier (NMDeviceEthernet *self, const gboolean carrier)
|
||||||
if (priv->carrier == carrier)
|
if (priv->carrier == carrier)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Clear any previous deferred action */
|
||||||
|
carrier_action_defer_clear (self);
|
||||||
|
|
||||||
priv->carrier = carrier;
|
priv->carrier = carrier;
|
||||||
g_object_notify (G_OBJECT (self), NM_DEVICE_ETHERNET_CARRIER);
|
g_object_notify (G_OBJECT (self), NM_DEVICE_ETHERNET_CARRIER);
|
||||||
|
|
||||||
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
|
state = nm_device_interface_get_state (NM_DEVICE_INTERFACE (self));
|
||||||
nm_info ("(%s): carrier now %s (device state %d)", nm_device_get_iface (NM_DEVICE (self)), carrier ? "ON" : "OFF", state);
|
nm_info ("(%s): carrier now %s (device state %d%s)",
|
||||||
if (state == NM_DEVICE_STATE_UNAVAILABLE) {
|
nm_device_get_iface (NM_DEVICE (self)),
|
||||||
if (carrier)
|
carrier ? "ON" : "OFF",
|
||||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER);
|
state,
|
||||||
} else if (state >= NM_DEVICE_STATE_DISCONNECTED) {
|
defer_action ? ", deferring action for 4 seconds" : "");
|
||||||
if (!carrier)
|
|
||||||
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER);
|
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
|
static void
|
||||||
|
|
@ -216,7 +256,7 @@ carrier_on (NMNetlinkMonitor *monitor,
|
||||||
if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
|
if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_carrier (NM_DEVICE_ETHERNET (device), TRUE);
|
set_carrier (self, TRUE, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -232,12 +272,23 @@ carrier_off (NMNetlinkMonitor *monitor,
|
||||||
|
|
||||||
/* Make sure signal is for us */
|
/* Make sure signal is for us */
|
||||||
if (idx == priv->ifindex) {
|
if (idx == priv->ifindex) {
|
||||||
|
NMDeviceState state;
|
||||||
|
gboolean defer = FALSE;
|
||||||
|
|
||||||
/* Ignore spurious netlink messages */
|
/* Ignore spurious netlink messages */
|
||||||
caps = nm_device_get_capabilities (device);
|
caps = nm_device_get_capabilities (device);
|
||||||
if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
|
if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_carrier (NM_DEVICE_ETHERNET (device), FALSE);
|
/* 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_interface_get_state (NM_DEVICE_INTERFACE (self));
|
||||||
|
if (state > NM_DEVICE_STATE_DISCONNECTED)
|
||||||
|
defer = TRUE;
|
||||||
|
|
||||||
|
set_carrier (self, FALSE, defer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,6 +338,10 @@ constructor (GType type,
|
||||||
} else
|
} else
|
||||||
priv->carrier = !!(ifflags & IFF_LOWER_UP);
|
priv->carrier = !!(ifflags & IFF_LOWER_UP);
|
||||||
|
|
||||||
|
nm_info ("(%s): carrier is %s",
|
||||||
|
nm_device_get_iface (NM_DEVICE (self)),
|
||||||
|
priv->carrier ? "ON" : "OFF");
|
||||||
|
|
||||||
/* Request link state again just in case an error occurred getting the
|
/* Request link state again just in case an error occurred getting the
|
||||||
* initial link state.
|
* initial link state.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1675,6 +1730,8 @@ dispose (GObject *object)
|
||||||
priv->link_disconnected_id = 0;
|
priv->link_disconnected_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
carrier_action_defer_clear (self);
|
||||||
|
|
||||||
if (priv->monitor) {
|
if (priv->monitor) {
|
||||||
g_object_unref (priv->monitor);
|
g_object_unref (priv->monitor);
|
||||||
priv->monitor = NULL;
|
priv->monitor = NULL;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue