mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-05 05:20:32 +01:00
core: track autoconnect for removed software devices (rh #1005913)
When an interface is manually disconnected NM remembers that, and prevents automatic activation of the device. However, software devices are removed when they are disconnected, and thus the state of the device is lost. We need to track autoconnect outside the device - hash table of interface names not allowed to activate automatically. Without that the device would be auto-activated again and again, even if explicitly disconnected. Test case: $ nmcli con add type bond ifname bb con-name bb-con $ nmcli con add type bond-slave ifname em1 con-name b1-con master bb $ nmcli dev disconnect bb https://bugzilla.redhat.com/show_bug.cgi?id=1005913
This commit is contained in:
parent
1a67f8df03
commit
f4dbf27410
3 changed files with 68 additions and 4 deletions
|
|
@ -42,6 +42,7 @@
|
|||
#include "nm-device.h"
|
||||
#include "nm-device-private.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-manager.h"
|
||||
#include "nm-platform.h"
|
||||
#include "nm-rdisc.h"
|
||||
#include "nm-lndp-rdisc.h"
|
||||
|
|
@ -4339,6 +4340,14 @@ disconnect_cb (NMDevice *device,
|
|||
g_error_free (local);
|
||||
} else {
|
||||
priv->autoconnect = FALSE;
|
||||
|
||||
/* Software devices are removed when manually disconnected and thus
|
||||
* we need to track the autoconnect flag outside the device.
|
||||
*/
|
||||
nm_manager_prevent_device_auto_connect (nm_manager_get (),
|
||||
nm_device_get_ip_iface (device),
|
||||
TRUE);
|
||||
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_DISCONNECTED,
|
||||
NM_DEVICE_STATE_REASON_USER_REQUESTED);
|
||||
|
|
|
|||
|
|
@ -263,6 +263,9 @@ typedef struct {
|
|||
|
||||
GHashTable *nm_bridges;
|
||||
|
||||
/* Track auto-activation for software devices */
|
||||
GHashTable *noauto_sw_devices;
|
||||
|
||||
gboolean startup;
|
||||
gboolean disposed;
|
||||
} NMManagerPrivate;
|
||||
|
|
@ -3096,13 +3099,29 @@ nm_manager_activate_connection (NMManager *manager,
|
|||
}
|
||||
|
||||
device = find_device_by_ip_iface (manager, iface);
|
||||
g_free (iface);
|
||||
if (!device) {
|
||||
/* Create it */
|
||||
/* Create the software device. Only exception is when:
|
||||
* - this is an auto-activation *and* the device denies auto-activation
|
||||
* at this time (the device was manually disconnected/deleted before)
|
||||
*/
|
||||
if (!nm_manager_can_device_auto_connect (manager, iface)) {
|
||||
if (dbus_sender) {
|
||||
/* Manual activation - allow device auto-activation again */
|
||||
nm_manager_prevent_device_auto_connect (manager, iface, FALSE);
|
||||
} else {
|
||||
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_AUTOCONNECT_NOT_ALLOWED,
|
||||
"'%s' does not allow automatic connections at this time => software device '%s' not created for '%s'",
|
||||
iface, nm_connection_get_id (connection), iface);
|
||||
g_free (iface);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
device = system_create_virtual_device (manager, connection);
|
||||
if (!device) {
|
||||
g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
|
||||
"Failed to create virtual interface");
|
||||
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE,
|
||||
"Failed to create virtual interface '%s'", iface);
|
||||
g_free (iface);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -3118,6 +3137,7 @@ nm_manager_activate_connection (NMManager *manager,
|
|||
NM_DEVICE_STATE_REASON_NONE);
|
||||
}
|
||||
}
|
||||
g_free (iface);
|
||||
}
|
||||
|
||||
if (!nm_device_can_activate (device, connection)) {
|
||||
|
|
@ -3498,6 +3518,30 @@ impl_manager_deactivate_connection (NMManager *self,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Track (software) devices that cannot auto activate.
|
||||
* It is needed especially for software devices, that can be removed and added
|
||||
* again. So we can't simply use a flag inside the device.
|
||||
*/
|
||||
void
|
||||
nm_manager_prevent_device_auto_connect (NMManager *manager, const char *ifname, gboolean prevent)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
||||
|
||||
if (prevent)
|
||||
g_hash_table_add (priv->noauto_sw_devices, g_strdup (ifname));
|
||||
else
|
||||
g_hash_table_remove (priv->noauto_sw_devices, ifname);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_manager_can_device_auto_connect (NMManager *manager, const char *ifname)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
|
||||
|
||||
return !g_hash_table_contains (priv->noauto_sw_devices, ifname);
|
||||
}
|
||||
|
||||
static void
|
||||
do_sleep_wake (NMManager *self)
|
||||
{
|
||||
|
|
@ -4575,6 +4619,8 @@ dispose (GObject *object)
|
|||
g_object_unref (priv->fw_monitor);
|
||||
}
|
||||
|
||||
g_hash_table_unref (priv->noauto_sw_devices);
|
||||
|
||||
g_slist_free (priv->factories);
|
||||
|
||||
if (priv->timestamp_update_id) {
|
||||
|
|
@ -4938,6 +4984,9 @@ nm_manager_init (NMManager *manager)
|
|||
KERNEL_FIRMWARE_DIR);
|
||||
}
|
||||
|
||||
/* Hash table storing software devices that should not auto activate */
|
||||
priv->noauto_sw_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||
|
||||
load_device_factories (manager);
|
||||
|
||||
/* Update timestamps in active connections */
|
||||
|
|
|
|||
|
|
@ -125,6 +125,12 @@ gboolean nm_manager_deactivate_connection (NMManager *manager,
|
|||
NMDeviceStateReason reason,
|
||||
GError **error);
|
||||
|
||||
void nm_manager_prevent_device_auto_connect (NMManager *manager,
|
||||
const char *ifname,
|
||||
gboolean prevent);
|
||||
gboolean nm_manager_can_device_auto_connect (NMManager *manager,
|
||||
const char *ifname);
|
||||
|
||||
/* State handling */
|
||||
|
||||
NMState nm_manager_get_state (NMManager *manager);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue