core: create devices first and realize them later
Unrealized devices aren't backed by kernel resources and so won't know all of their attributes. That means three things: 1) they must update their attributes when they become realized 2) they must clear those attributes when unrealized 3) they must be looser in checking compatible connections until they are realized This requires that the setup() function be split into two parts, start & finish, because finish must be run after add_device() Also, we can simplify whether to pay attention to 'recheck-assume', which is now dependent on priv->is_nm_owned, because the only case where NM should *not* listen for the 'recheck-assume' signal is when the device is a software device created by NM itself. That logic was previously spread across the callers of add_device() but is now consolidated into nm-manager.c::device_realized() and nm-device.c::nm_device_create_and_realize().
This commit is contained in:

committed by
Thomas Haller

parent
b7eb622c24
commit
4dbaac4ba2
@@ -97,7 +97,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
||||
return FALSE;
|
||||
|
||||
mac_address = nm_setting_bridge_get_mac_address (s_bridge);
|
||||
if (mac_address) {
|
||||
if (mac_address && nm_device_is_real (device)) {
|
||||
const char *hw_addr;
|
||||
|
||||
hw_addr = nm_device_get_hw_address (device);
|
||||
|
@@ -305,9 +305,9 @@ nm_device_ethernet_init (NMDeviceEthernet *self)
|
||||
}
|
||||
|
||||
static void
|
||||
setup (NMDevice *device, NMPlatformLink *plink)
|
||||
setup_start (NMDevice *device, NMPlatformLink *plink)
|
||||
{
|
||||
NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->setup (device, plink);
|
||||
NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->setup_start (device, plink);
|
||||
|
||||
g_object_notify (G_OBJECT (device), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS);
|
||||
}
|
||||
@@ -1716,7 +1716,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
|
||||
object_class->set_property = set_property;
|
||||
|
||||
parent_class->get_generic_capabilities = get_generic_capabilities;
|
||||
parent_class->setup = setup;
|
||||
parent_class->setup_start = setup_start;
|
||||
parent_class->check_connection_compatible = check_connection_compatible;
|
||||
parent_class->complete_connection = complete_connection;
|
||||
parent_class->new_default_connection = new_default_connection;
|
||||
|
@@ -61,13 +61,13 @@ get_type_description (NMDevice *device)
|
||||
}
|
||||
|
||||
static void
|
||||
setup (NMDevice *device, NMPlatformLink *plink)
|
||||
setup_start (NMDevice *device, NMPlatformLink *plink)
|
||||
{
|
||||
NMDeviceGeneric *self = NM_DEVICE_GENERIC (device);
|
||||
NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self);
|
||||
int ifindex;
|
||||
|
||||
NM_DEVICE_CLASS (nm_device_generic_parent_class)->setup (device, plink);
|
||||
NM_DEVICE_CLASS (nm_device_generic_parent_class)->setup_start (device, plink);
|
||||
|
||||
g_clear_pointer (&priv->type_description, g_free);
|
||||
ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self));
|
||||
@@ -203,7 +203,7 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass)
|
||||
object_class->get_property = get_property;
|
||||
object_class->set_property = set_property;
|
||||
|
||||
parent_class->setup = setup;
|
||||
parent_class->setup_start = setup_start;
|
||||
parent_class->get_generic_capabilities = get_generic_capabilities;
|
||||
parent_class->get_type_description = get_type_description;
|
||||
parent_class->check_connection_compatible = check_connection_compatible;
|
||||
|
@@ -149,7 +149,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
||||
if (!s_infiniband)
|
||||
return FALSE;
|
||||
|
||||
if (s_infiniband) {
|
||||
if (nm_device_is_real (device)) {
|
||||
const char *mac;
|
||||
|
||||
mac = nm_setting_infiniband_get_mac_address (s_infiniband);
|
||||
|
@@ -503,41 +503,43 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
||||
if (!s_ip_tunnel)
|
||||
return FALSE;
|
||||
|
||||
/* Check parent interface; could be an interface name or a UUID */
|
||||
parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel);
|
||||
if (parent) {
|
||||
if (!match_parent (priv->parent, parent))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode)
|
||||
return FALSE;
|
||||
|
||||
if (!address_equal_pp (priv->addr_family,
|
||||
nm_setting_ip_tunnel_get_local (s_ip_tunnel),
|
||||
priv->local))
|
||||
return FALSE;
|
||||
if (nm_device_is_real (device)) {
|
||||
/* Check parent interface; could be an interface name or a UUID */
|
||||
parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel);
|
||||
if (parent) {
|
||||
if (!match_parent (priv->parent, parent))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!address_equal_pp (priv->addr_family,
|
||||
nm_setting_ip_tunnel_get_remote (s_ip_tunnel),
|
||||
priv->remote))
|
||||
return FALSE;
|
||||
|
||||
if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl)
|
||||
return FALSE;
|
||||
|
||||
if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos)
|
||||
return FALSE;
|
||||
|
||||
if (priv->addr_family == AF_INET) {
|
||||
if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery)
|
||||
return FALSE;
|
||||
} else {
|
||||
if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit)
|
||||
if (!address_equal_pp (priv->addr_family,
|
||||
nm_setting_ip_tunnel_get_local (s_ip_tunnel),
|
||||
priv->local))
|
||||
return FALSE;
|
||||
|
||||
if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label)
|
||||
if (!address_equal_pp (priv->addr_family,
|
||||
nm_setting_ip_tunnel_get_remote (s_ip_tunnel),
|
||||
priv->remote))
|
||||
return FALSE;
|
||||
|
||||
if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl)
|
||||
return FALSE;
|
||||
|
||||
if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos)
|
||||
return FALSE;
|
||||
|
||||
if (priv->addr_family == AF_INET) {
|
||||
if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery)
|
||||
return FALSE;
|
||||
} else {
|
||||
if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit)
|
||||
return FALSE;
|
||||
|
||||
if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -751,9 +753,9 @@ create_and_realize (NMDevice *device,
|
||||
}
|
||||
|
||||
static void
|
||||
setup (NMDevice *device, NMPlatformLink *plink)
|
||||
setup_start (NMDevice *device, NMPlatformLink *plink)
|
||||
{
|
||||
NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->setup (device, plink);
|
||||
NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->setup_start (device, plink);
|
||||
|
||||
update_properties (device);
|
||||
}
|
||||
@@ -847,7 +849,7 @@ nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass)
|
||||
device_class->check_connection_compatible = check_connection_compatible;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->realize = realize;
|
||||
device_class->setup = setup;
|
||||
device_class->setup_start = setup_start;
|
||||
device_class->unrealize = unrealize;
|
||||
|
||||
device_class->connection_type = NM_SETTING_IP_TUNNEL_SETTING_NAME;
|
||||
|
@@ -226,6 +226,13 @@ realize (NMDevice *device, NMPlatformLink *plink, GError **error)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_start (NMDevice *device, NMPlatformLink *plink)
|
||||
{
|
||||
NM_DEVICE_CLASS (nm_device_tun_parent_class)->setup_start (device, plink);
|
||||
reload_tun_properties (device);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_connection_compatible (NMDevice *device, NMConnection *connection)
|
||||
{
|
||||
@@ -235,8 +242,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
||||
NMSettingTun *s_tun;
|
||||
gint64 user, group;
|
||||
|
||||
reload_tun_properties (self);
|
||||
|
||||
if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection))
|
||||
return FALSE;
|
||||
|
||||
@@ -244,23 +249,25 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
||||
if (!s_tun)
|
||||
return FALSE;
|
||||
|
||||
mode = tun_mode_from_string (priv->mode);
|
||||
if (mode != nm_setting_tun_get_mode (s_tun))
|
||||
return FALSE;
|
||||
if (nm_device_is_real (device)) {
|
||||
mode = tun_mode_from_string (priv->mode);
|
||||
if (mode != nm_setting_tun_get_mode (s_tun))
|
||||
return FALSE;
|
||||
|
||||
user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1);
|
||||
group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1);
|
||||
user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1);
|
||||
group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1);
|
||||
|
||||
if (user != priv->props.owner)
|
||||
return FALSE;
|
||||
if (group != priv->props.group)
|
||||
return FALSE;
|
||||
if (nm_setting_tun_get_pi (s_tun) == priv->props.no_pi)
|
||||
return FALSE;
|
||||
if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr)
|
||||
return FALSE;
|
||||
if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue)
|
||||
return FALSE;
|
||||
if (user != priv->props.owner)
|
||||
return FALSE;
|
||||
if (group != priv->props.group)
|
||||
return FALSE;
|
||||
if (nm_setting_tun_get_pi (s_tun) == priv->props.no_pi)
|
||||
return FALSE;
|
||||
if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr)
|
||||
return FALSE;
|
||||
if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -367,6 +374,7 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
|
||||
device_class->check_connection_compatible = check_connection_compatible;
|
||||
device_class->create_and_realize = create_and_realize;
|
||||
device_class->realize = realize;
|
||||
device_class->setup_start = setup_start;
|
||||
device_class->unrealize = unrealize;
|
||||
device_class->update_connection = update_connection;
|
||||
|
||||
|
@@ -148,12 +148,12 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent)
|
||||
}
|
||||
|
||||
static void
|
||||
setup (NMDevice *device, NMPlatformLink *plink)
|
||||
setup_start (NMDevice *device, NMPlatformLink *plink)
|
||||
{
|
||||
NMDeviceVlan *self = NM_DEVICE_VLAN (device);
|
||||
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
|
||||
|
||||
NM_DEVICE_CLASS (nm_device_vlan_parent_class)->setup (device, plink);
|
||||
NM_DEVICE_CLASS (nm_device_vlan_parent_class)->setup_start (device, plink);
|
||||
|
||||
_LOGI (LOGD_HW | LOGD_VLAN, "VLAN ID %d with parent %s",
|
||||
priv->vlan_id, nm_device_get_iface (priv->parent));
|
||||
@@ -311,6 +311,9 @@ notify_new_device_added (NMDevice *device, NMDevice *new_device)
|
||||
if (priv->parent)
|
||||
return;
|
||||
|
||||
if (!nm_device_is_real (device))
|
||||
return;
|
||||
|
||||
plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink);
|
||||
if (!plnk) {
|
||||
_LOGW (LOGD_VLAN, "failed to get VLAN interface info while checking added component.");
|
||||
@@ -397,18 +400,21 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
|
||||
if (!s_vlan)
|
||||
return FALSE;
|
||||
|
||||
if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id)
|
||||
return FALSE;
|
||||
/* Before the device is realized some properties will not be set */
|
||||
if (nm_device_is_real (device)) {
|
||||
if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id)
|
||||
return FALSE;
|
||||
|
||||
/* Check parent interface; could be an interface name or a UUID */
|
||||
parent = nm_setting_vlan_get_parent (s_vlan);
|
||||
if (parent) {
|
||||
if (!match_parent (NM_DEVICE_VLAN (device), parent))
|
||||
return FALSE;
|
||||
} else {
|
||||
/* Parent could be a MAC address in an NMSettingWired */
|
||||
if (!match_hwaddr (device, connection, TRUE))
|
||||
return FALSE;
|
||||
/* Check parent interface; could be an interface name or a UUID */
|
||||
parent = nm_setting_vlan_get_parent (s_vlan);
|
||||
if (parent) {
|
||||
if (!match_parent (NM_DEVICE_VLAN (device), parent))
|
||||
return FALSE;
|
||||
} else {
|
||||
/* Parent could be a MAC address in an NMSettingWired */
|
||||
if (!match_hwaddr (device, connection, TRUE))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure the interface name matches. If not specified we assume a match
|
||||
@@ -672,7 +678,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
|
||||
|
||||
parent_class->create_and_realize = create_and_realize;
|
||||
parent_class->realize = realize;
|
||||
parent_class->setup = setup;
|
||||
parent_class->setup_start = setup_start;
|
||||
parent_class->unrealize = unrealize;
|
||||
parent_class->get_generic_capabilities = get_generic_capabilities;
|
||||
parent_class->bring_up = bring_up;
|
||||
|
@@ -133,11 +133,11 @@ link_changed (NMDevice *device, NMPlatformLink *info)
|
||||
}
|
||||
|
||||
static void
|
||||
setup (NMDevice *device, NMPlatformLink *plink)
|
||||
setup_start (NMDevice *device, NMPlatformLink *plink)
|
||||
{
|
||||
g_assert (plink->type == NM_LINK_TYPE_VXLAN);
|
||||
|
||||
NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->setup (device, plink);
|
||||
NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->setup_start (device, plink);
|
||||
|
||||
update_properties (device);
|
||||
}
|
||||
@@ -247,7 +247,7 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
|
||||
object_class->get_property = get_property;
|
||||
|
||||
device_class->link_changed = link_changed;
|
||||
device_class->setup = setup;
|
||||
device_class->setup_start = setup_start;
|
||||
device_class->unrealize = unrealize;
|
||||
|
||||
/* properties */
|
||||
|
@@ -556,7 +556,7 @@ nm_device_get_iface (NMDevice *self)
|
||||
int
|
||||
nm_device_get_ifindex (NMDevice *self)
|
||||
{
|
||||
g_return_val_if_fail (self != NULL, 0);
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), 0);
|
||||
|
||||
return NM_DEVICE_GET_PRIVATE (self)->ifindex;
|
||||
}
|
||||
@@ -1152,8 +1152,7 @@ nm_device_release_one_slave (NMDevice *self, NMDevice *slave, gboolean configure
|
||||
static gboolean
|
||||
can_unmanaged_external_down (NMDevice *self)
|
||||
{
|
||||
return nm_device_is_software (self)
|
||||
&& !nm_device_get_is_nm_owned (self);
|
||||
return nm_device_is_software (self) && !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1385,23 +1384,31 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier)
|
||||
}
|
||||
|
||||
static void
|
||||
device_set_master (NMDevice *self, int ifindex)
|
||||
device_recheck_slave_status (NMDevice *self, NMPlatformLink *plink)
|
||||
{
|
||||
NMDevice *master;
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
master = nm_manager_get_device_by_ifindex (nm_manager_get (), ifindex);
|
||||
if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave) {
|
||||
g_clear_object (&priv->master);
|
||||
priv->master = g_object_ref (master);
|
||||
nm_device_master_add_slave (master, self, FALSE);
|
||||
} else if (master) {
|
||||
_LOGI (LOGD_DEVICE, "enslaved to non-master-type device %s; ignoring",
|
||||
nm_device_get_iface (master));
|
||||
} else {
|
||||
_LOGW (LOGD_DEVICE, "enslaved to unknown device %d %s",
|
||||
ifindex,
|
||||
nm_platform_link_get_name (NM_PLATFORM_GET, ifindex));
|
||||
g_return_if_fail (plink != NULL);
|
||||
|
||||
if (priv->enslaved && plink->master != nm_device_get_ifindex (priv->master))
|
||||
nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||
|
||||
if (plink->master && !priv->enslaved) {
|
||||
NMDevice *master;
|
||||
|
||||
master = nm_manager_get_device_by_ifindex (nm_manager_get (), plink->master);
|
||||
if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave) {
|
||||
g_clear_object (&priv->master);
|
||||
priv->master = g_object_ref (master);
|
||||
nm_device_master_add_slave (master, self, FALSE);
|
||||
} else if (master) {
|
||||
_LOGI (LOGD_DEVICE, "enslaved to non-master-type device %s; ignoring",
|
||||
nm_device_get_iface (master));
|
||||
} else {
|
||||
_LOGW (LOGD_DEVICE, "enslaved to unknown device %d %s",
|
||||
plink->master,
|
||||
nm_platform_link_get_name (NM_PLATFORM_GET, plink->master));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1449,6 +1456,12 @@ device_link_changed (NMDevice *self)
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_MTU);
|
||||
}
|
||||
|
||||
if (info.driver && g_strcmp0 (priv->driver, info.driver) != 0) {
|
||||
g_free (priv->driver);
|
||||
priv->driver = g_strdup (info.driver);
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER);
|
||||
}
|
||||
|
||||
if (info.name[0] && strcmp (priv->iface, info.name) != 0) {
|
||||
_LOGI (LOGD_DEVICE, "interface index %d renamed iface from '%s' to '%s'",
|
||||
priv->ifindex, priv->iface, info.name);
|
||||
@@ -1471,15 +1484,6 @@ device_link_changed (NMDevice *self)
|
||||
nm_device_emit_recheck_auto_activate (self);
|
||||
}
|
||||
|
||||
/* Update slave status for external changes */
|
||||
if (priv->enslaved && info.master != nm_device_get_ifindex (priv->master))
|
||||
nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
|
||||
if (info.master && !priv->enslaved) {
|
||||
device_set_master (self, info.master);
|
||||
if (priv->master)
|
||||
nm_device_enslave_slave (priv->master, self, NULL);
|
||||
}
|
||||
|
||||
if (priv->rdisc && nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &token_iid)) {
|
||||
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
|
||||
if (nm_rdisc_set_iid (priv->rdisc, token_iid))
|
||||
@@ -1562,6 +1566,7 @@ device_link_changed (NMDevice *self)
|
||||
if (emit_link_initialized)
|
||||
g_signal_emit (self, signals[LINK_INITIALIZED], 0);
|
||||
|
||||
device_recheck_slave_status (self, &info);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
@@ -1635,7 +1640,8 @@ link_changed (NMDevice *self, NMPlatformLink *info)
|
||||
* @plink: an existing platform link or %NULL
|
||||
* @error: location to store error, or %NULL
|
||||
*
|
||||
* Initializes and sets up the device using existing backing resources.
|
||||
* Initializes and sets up the device using existing backing resources. Before
|
||||
* the device is ready for use nm_device_setup_finish() must be called.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE on error
|
||||
*/
|
||||
@@ -1648,7 +1654,7 @@ nm_device_realize (NMDevice *self, NMPlatformLink *plink, GError **error)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NM_DEVICE_GET_CLASS (self)->setup (self, plink);
|
||||
NM_DEVICE_GET_CLASS (self)->setup_start (self, plink);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1671,15 +1677,20 @@ nm_device_create_and_realize (NMDevice *self,
|
||||
NMDevice *parent,
|
||||
GError **error)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMPlatformLink plink = { .type = NM_LINK_TYPE_UNKNOWN };
|
||||
|
||||
/* Must be set before device is realized */
|
||||
priv->is_nm_owned = !nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface);
|
||||
|
||||
/* Create any resources the device needs */
|
||||
if (NM_DEVICE_GET_CLASS (self)->create_and_realize) {
|
||||
if (!NM_DEVICE_GET_CLASS (self)->create_and_realize (self, connection, parent, &plink, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
NM_DEVICE_GET_CLASS (self)->setup (self, (plink.type != NM_LINK_TYPE_UNKNOWN) ? &plink : NULL);
|
||||
NM_DEVICE_GET_CLASS (self)->setup_start (self, (plink.type != NM_LINK_TYPE_UNKNOWN) ? &plink : NULL);
|
||||
nm_device_setup_finish (self, (plink.type != NM_LINK_TYPE_UNKNOWN) ? &plink : NULL);
|
||||
|
||||
g_return_val_if_fail (nm_device_check_connection_compatible (self, connection), TRUE);
|
||||
return TRUE;
|
||||
@@ -1742,7 +1753,7 @@ check_carrier (NMDevice *self)
|
||||
}
|
||||
|
||||
static void
|
||||
setup (NMDevice *self, NMPlatformLink *plink)
|
||||
setup_start (NMDevice *self, NMPlatformLink *plink)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
static guint32 id = 0;
|
||||
@@ -1751,6 +1762,7 @@ setup (NMDevice *self, NMPlatformLink *plink)
|
||||
g_return_if_fail (priv->ip_ifindex <= 0);
|
||||
g_return_if_fail (priv->ip_iface == NULL);
|
||||
|
||||
/* Balanced by a thaw in nm_device_setup_finish() */
|
||||
g_object_freeze_notify (G_OBJECT (self));
|
||||
|
||||
if (plink) {
|
||||
@@ -1759,7 +1771,7 @@ setup (NMDevice *self, NMPlatformLink *plink)
|
||||
}
|
||||
|
||||
if (priv->ifindex > 0) {
|
||||
_LOGD (LOGD_DEVICE, "setup(): %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), priv->ifindex);
|
||||
_LOGD (LOGD_DEVICE, "setup_start(): %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), priv->ifindex);
|
||||
|
||||
priv->physical_port_id = nm_platform_link_get_physical_port_id (NM_PLATFORM_GET, priv->ifindex);
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID);
|
||||
@@ -1844,17 +1856,29 @@ setup (NMDevice *self, NMPlatformLink *plink)
|
||||
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES);
|
||||
|
||||
/* Enslave ourselves */
|
||||
if (priv->ifindex > 0) {
|
||||
int master = nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex);
|
||||
|
||||
if (master > 0)
|
||||
device_set_master (self, master);
|
||||
}
|
||||
|
||||
priv->real = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_finish (NMDevice *self, NMPlatformLink *plink)
|
||||
{
|
||||
if (plink) {
|
||||
update_device_from_platform_link (self, plink);
|
||||
device_recheck_slave_status (self, plink);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nm_device_setup_finish (NMDevice *self, NMPlatformLink *plink)
|
||||
{
|
||||
NM_DEVICE_GET_CLASS (self)->setup_finish (self, plink);
|
||||
|
||||
NM_DEVICE_GET_PRIVATE (self)->real = TRUE;
|
||||
g_object_notify (G_OBJECT (self), NM_DEVICE_REAL);
|
||||
|
||||
nm_device_recheck_available_connections (self);
|
||||
|
||||
/* Balanced by a freeze in setup_start() */
|
||||
g_object_thaw_notify (G_OBJECT (self));
|
||||
}
|
||||
|
||||
@@ -2810,7 +2834,8 @@ nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection)
|
||||
static gboolean
|
||||
nm_device_can_assume_connections (NMDevice *self)
|
||||
{
|
||||
return !!NM_DEVICE_GET_CLASS (self)->update_connection;
|
||||
return !!NM_DEVICE_GET_CLASS (self)->update_connection
|
||||
&& !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6547,14 +6572,6 @@ nm_device_get_is_nm_owned (NMDevice *self)
|
||||
return NM_DEVICE_GET_PRIVATE (self)->is_nm_owned;
|
||||
}
|
||||
|
||||
void
|
||||
nm_device_set_nm_owned (NMDevice *self)
|
||||
{
|
||||
g_return_if_fail (NM_IS_DEVICE (self));
|
||||
|
||||
NM_DEVICE_GET_PRIVATE (self)->is_nm_owned = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete_on_deactivate_link_delete
|
||||
*
|
||||
@@ -8461,6 +8478,7 @@ _nm_device_check_connection_available (NMDevice *self,
|
||||
&& nm_device_get_unmanaged (self, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT))
|
||||
return FALSE;
|
||||
if ( state < NM_DEVICE_STATE_DISCONNECTED
|
||||
&& !nm_device_is_software (self)
|
||||
&& ( ( !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)
|
||||
@@ -10324,7 +10342,8 @@ nm_device_class_init (NMDeviceClass *klass)
|
||||
klass->check_connection_compatible = check_connection_compatible;
|
||||
klass->check_connection_available = check_connection_available;
|
||||
klass->can_unmanaged_external_down = can_unmanaged_external_down;
|
||||
klass->setup = setup;
|
||||
klass->setup_start = setup_start;
|
||||
klass->setup_finish = setup_finish;
|
||||
klass->unrealize = unrealize;
|
||||
klass->is_up = is_up;
|
||||
klass->bring_up = bring_up;
|
||||
|
@@ -174,14 +174,28 @@ typedef struct {
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* setup():
|
||||
* setup_start():
|
||||
* @self: the #NMDevice
|
||||
* @plink: the #NMPlatformLink if backed by a kernel netdevice
|
||||
*
|
||||
* Update the device from backing resource properties (like hardware
|
||||
* addresses, carrier states, driver/firmware info, etc).
|
||||
* addresses, carrier states, driver/firmware info, etc). This function
|
||||
* should only change properties for this device, and should not perform
|
||||
* any tasks that affect other interfaces (like master/slave or parent/child
|
||||
* stuff).
|
||||
*/
|
||||
void (*setup) (NMDevice *self, NMPlatformLink *plink);
|
||||
void (*setup_start) (NMDevice *self, NMPlatformLink *plink);
|
||||
|
||||
/**
|
||||
* setup_finish():
|
||||
* @self: the #NMDevice
|
||||
* @plink: the #NMPlatformLink if backed by a kernel netdevice
|
||||
*
|
||||
* Update the device's master/slave or parent/child relationships from
|
||||
* backing resource properties. After this function finishes, the device
|
||||
* is ready for network connectivity.
|
||||
*/
|
||||
void (*setup_finish) (NMDevice *self, NMPlatformLink *plink);
|
||||
|
||||
/**
|
||||
* unrealize():
|
||||
@@ -466,7 +480,6 @@ void nm_device_set_unmanaged_initial (NMDevice *device,
|
||||
gboolean unmanaged);
|
||||
|
||||
gboolean nm_device_get_is_nm_owned (NMDevice *device);
|
||||
void nm_device_set_nm_owned (NMDevice *device);
|
||||
|
||||
gboolean nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps);
|
||||
|
||||
@@ -477,6 +490,8 @@ gboolean nm_device_create_and_realize (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
NMDevice *parent,
|
||||
GError **error);
|
||||
void nm_device_setup_finish (NMDevice *self,
|
||||
NMPlatformLink *plink);
|
||||
gboolean nm_device_unrealize (NMDevice *device,
|
||||
gboolean remove_resources,
|
||||
GError **error);
|
||||
|
@@ -424,9 +424,9 @@ periodic_update_cb (gpointer user_data)
|
||||
}
|
||||
|
||||
static void
|
||||
setup (NMDevice *device, NMPlatformLink *plink)
|
||||
setup_start (NMDevice *device, NMPlatformLink *plink)
|
||||
{
|
||||
NM_DEVICE_CLASS (nm_device_wifi_parent_class)->setup (device, plink);
|
||||
NM_DEVICE_CLASS (nm_device_wifi_parent_class)->setup_start (device, plink);
|
||||
|
||||
g_object_notify (G_OBJECT (device), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
|
||||
}
|
||||
@@ -3040,7 +3040,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
|
||||
object_class->dispose = dispose;
|
||||
object_class->finalize = finalize;
|
||||
|
||||
parent_class->setup = setup;
|
||||
parent_class->setup_start = setup_start;
|
||||
parent_class->bring_up = bring_up;
|
||||
parent_class->can_auto_connect = can_auto_connect;
|
||||
parent_class->is_available = is_available;
|
||||
|
@@ -598,17 +598,17 @@ master_state_cb (NMActiveConnection *master,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data);
|
||||
NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self);
|
||||
NMActiveConnectionState master_state = nm_active_connection_get_state (master);
|
||||
NMDevice *master_device = nm_active_connection_get_device (master);
|
||||
|
||||
check_master_ready (self);
|
||||
|
||||
_LOGD ("master ActiveConnection [%p] state now '%s' (%d)",
|
||||
master, state_to_string (master_state), master_state);
|
||||
|
||||
if ( master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING
|
||||
&& !priv->master_ready) {
|
||||
/* Master failed without ever creating its device */
|
||||
if ( master_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATING
|
||||
&& (!master_device || !nm_device_is_real (master_device))) {
|
||||
/* Master failed without ever creating or realizing its device */
|
||||
if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed)
|
||||
NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self);
|
||||
}
|
||||
|
323
src/nm-manager.c
323
src/nm-manager.c
@@ -58,7 +58,7 @@
|
||||
#include "nmdbus-manager.h"
|
||||
#include "nmdbus-device.h"
|
||||
|
||||
static void add_device (NMManager *self, NMDevice *device, gboolean try_assume);
|
||||
static void add_device (NMManager *self, NMDevice *device);
|
||||
|
||||
static NMActiveConnection *_new_active_connection (NMManager *self,
|
||||
NMConnection *connection,
|
||||
@@ -487,8 +487,11 @@ find_device_by_ip_iface (NMManager *self, const gchar *iface)
|
||||
g_return_val_if_fail (iface != NULL, NULL);
|
||||
|
||||
for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = g_slist_next (iter)) {
|
||||
if (g_strcmp0 (nm_device_get_ip_iface (NM_DEVICE (iter->data)), iface) == 0)
|
||||
return NM_DEVICE (iter->data);
|
||||
NMDevice *candidate = iter->data;
|
||||
|
||||
if ( nm_device_is_real (candidate)
|
||||
&& g_strcmp0 (nm_device_get_ip_iface (candidate), iface) == 0)
|
||||
return candidate;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -840,6 +843,8 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection)
|
||||
NMDevice *parent, *first_compatible = NULL;
|
||||
GSList *iter;
|
||||
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||
|
||||
factory = nm_device_factory_manager_find_factory_for_connection (connection);
|
||||
if (!factory)
|
||||
return NULL;
|
||||
@@ -849,7 +854,7 @@ find_parent_device_for_connection (NMManager *self, NMConnection *connection)
|
||||
return NULL;
|
||||
|
||||
/* Try as an interface name */
|
||||
parent = find_device_by_ip_iface (self, parent_name);
|
||||
parent = find_device_by_iface (self, parent_name);
|
||||
if (parent)
|
||||
return parent;
|
||||
|
||||
@@ -964,10 +969,9 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
NMDeviceFactory *factory;
|
||||
GSList *iter;
|
||||
char *iface = NULL;
|
||||
GSList *connections, *iter;
|
||||
gs_free char *iface = NULL;
|
||||
NMDevice *device = NULL, *parent = NULL;
|
||||
gboolean nm_owned = FALSE;
|
||||
|
||||
g_return_val_if_fail (NM_IS_MANAGER (self), NULL);
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||
@@ -989,7 +993,7 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
|
||||
NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_FAILED,
|
||||
"interface name '%s' already created", iface);
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1003,79 +1007,61 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
|
||||
NM_MANAGER_ERROR_FAILED,
|
||||
"NetworkManager plugin for '%s' unavailable",
|
||||
nm_connection_get_connection_type (connection));
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nm_owned = !nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
|
||||
|
||||
device = nm_device_factory_create_device (factory, iface, NULL, connection, NULL, error);
|
||||
if (device) {
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
add_device (self, device);
|
||||
|
||||
/* Add device takes a reference that NMManager still owns, so it's
|
||||
* safe to unref here and still return @device.
|
||||
*/
|
||||
g_object_unref (device);
|
||||
|
||||
/* Create backing resources if the device has any autoconnect connections */
|
||||
connections = nm_settings_get_connections (priv->settings);
|
||||
for (iter = connections; iter; iter = g_slist_next (iter)) {
|
||||
NMConnection *candidate = iter->data;
|
||||
NMSettingConnection *s_con;
|
||||
|
||||
if (!nm_device_check_connection_compatible (device, candidate))
|
||||
continue;
|
||||
|
||||
s_con = nm_connection_get_setting_connection (candidate);
|
||||
g_assert (s_con);
|
||||
if (!nm_setting_connection_get_autoconnect (s_con))
|
||||
continue;
|
||||
|
||||
/* Create any backing resources the device needs */
|
||||
if (!nm_device_create_and_realize (device, connection, parent, error)) {
|
||||
g_clear_object (&device);
|
||||
goto out;
|
||||
remove_device (self, device, FALSE, TRUE);
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
if (nm_owned)
|
||||
nm_device_set_nm_owned (device);
|
||||
|
||||
/* If it was created by NM there's no connection to assume, but if it
|
||||
* previously existed there might be one.
|
||||
*/
|
||||
add_device (self, device, !nm_owned);
|
||||
|
||||
/* Add device takes a reference that NMManager still owns, so it's
|
||||
* safe to unref here and still return @device.
|
||||
*/
|
||||
g_object_unref (device);
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
g_free (iface);
|
||||
return device;
|
||||
}
|
||||
|
||||
static void
|
||||
system_create_virtual_devices (NMManager *self)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
GSList *iter, *connections;
|
||||
|
||||
nm_log_dbg (LOGD_CORE, "creating virtual devices...");
|
||||
|
||||
connections = nm_settings_get_connections (priv->settings);
|
||||
for (iter = connections; iter; iter = g_slist_next (iter)) {
|
||||
NMConnection *connection = iter->data;
|
||||
|
||||
/* We only create a virtual interface if the connection can autoconnect */
|
||||
if ( nm_connection_is_virtual (connection)
|
||||
&& nm_settings_connection_can_autoconnect (NM_SETTINGS_CONNECTION (connection)))
|
||||
system_create_virtual_device (self, connection, NULL);
|
||||
}
|
||||
g_slist_free (connections);
|
||||
}
|
||||
|
||||
static void
|
||||
connection_added (NMSettings *settings,
|
||||
NMSettingsConnection *settings_connection,
|
||||
NMConnection *connection,
|
||||
NMManager *manager)
|
||||
{
|
||||
NMConnection *connection = NM_CONNECTION (settings_connection);
|
||||
|
||||
if (nm_connection_is_virtual (connection)) {
|
||||
NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
|
||||
|
||||
g_assert (s_con);
|
||||
if (nm_setting_connection_get_autoconnect (s_con))
|
||||
system_create_virtual_device (manager, connection, NULL);
|
||||
}
|
||||
if (nm_connection_is_virtual (connection))
|
||||
system_create_virtual_device (manager, connection, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
connection_changed (NMSettings *settings,
|
||||
NMSettingsConnection *connection,
|
||||
NMConnection *connection,
|
||||
NMManager *manager)
|
||||
{
|
||||
/* FIXME: Some virtual devices may need to be updated in the future. */
|
||||
if (nm_connection_is_virtual (connection))
|
||||
system_create_virtual_device (manager, connection, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1590,17 +1576,25 @@ assume_connection (NMManager *self, NMDevice *device, NMSettingsConnection *conn
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
can_start_device (NMManager *self, NMDevice *device)
|
||||
{
|
||||
return nm_device_is_real (device)
|
||||
&& !manager_sleeping (self)
|
||||
&& !nm_device_get_unmanaged (device, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
recheck_assume_connection (NMDevice *device, gpointer user_data)
|
||||
{
|
||||
NMManager *self = NM_MANAGER (user_data);
|
||||
NMSettingsConnection *connection;
|
||||
gboolean was_unmanaged = FALSE, success, generated;
|
||||
gboolean was_unmanaged = FALSE, success, generated = FALSE;
|
||||
NMDeviceState state;
|
||||
|
||||
if (manager_sleeping (self))
|
||||
return FALSE;
|
||||
if (nm_device_get_unmanaged (device, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT))
|
||||
g_return_val_if_fail (!nm_device_get_is_nm_owned (device), FALSE);
|
||||
|
||||
if (!can_start_device (self, device))
|
||||
return FALSE;
|
||||
|
||||
state = nm_device_get_state (device);
|
||||
@@ -1671,26 +1665,51 @@ device_ip_iface_changed (NMDevice *device,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_realized (NMDevice *device,
|
||||
GParamSpec *pspec,
|
||||
NMManager *self)
|
||||
{
|
||||
int ifindex;
|
||||
gboolean assumed = FALSE;
|
||||
|
||||
/* Loopback device never gets managed */
|
||||
ifindex = nm_device_get_ifindex (device);
|
||||
if (ifindex > 0 && nm_platform_link_get_type (NM_PLATFORM_GET, ifindex) == NM_LINK_TYPE_LOOPBACK)
|
||||
return;
|
||||
|
||||
if (!can_start_device (self, device))
|
||||
return;
|
||||
|
||||
if (!nm_device_get_is_nm_owned (device)) {
|
||||
assumed = recheck_assume_connection (device, self);
|
||||
g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME,
|
||||
G_CALLBACK (recheck_assume_connection), self);
|
||||
}
|
||||
|
||||
if (!assumed && nm_device_get_managed (device)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add_device:
|
||||
* @self: the #NMManager
|
||||
* @device: the #NMDevice to add
|
||||
* @try_assume: %TRUE if existing connection (if any) should be assumed
|
||||
*
|
||||
* If successful, this function will increase the references count of @device.
|
||||
* Callers should decrease the reference count.
|
||||
*/
|
||||
static void
|
||||
add_device (NMManager *self, NMDevice *device, gboolean try_assume)
|
||||
add_device (NMManager *self, NMDevice *device)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
const char *iface, *driver, *type_desc;
|
||||
const char *iface, *type_desc;
|
||||
const GSList *unmanaged_specs;
|
||||
gboolean user_unmanaged, sleeping;
|
||||
gboolean enabled = FALSE;
|
||||
RfKillType rtype;
|
||||
GSList *iter, *remove = NULL;
|
||||
gboolean connection_assumed = FALSE;
|
||||
int ifindex;
|
||||
const char *dbus_path;
|
||||
|
||||
@@ -1738,6 +1757,9 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_IP_IFACE,
|
||||
G_CALLBACK (device_ip_iface_changed),
|
||||
self);
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_REAL,
|
||||
G_CALLBACK (device_realized),
|
||||
self);
|
||||
|
||||
if (priv->startup) {
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_HAS_PENDING_ACTION,
|
||||
@@ -1752,52 +1774,29 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
|
||||
rtype = nm_device_get_rfkill_type (device);
|
||||
if (rtype != RFKILL_TYPE_UNKNOWN) {
|
||||
nm_manager_rfkill_update (self, rtype);
|
||||
enabled = radio_enabled_for_type (self, rtype, TRUE);
|
||||
nm_device_set_enabled (device, enabled);
|
||||
nm_device_set_enabled (device, radio_enabled_for_type (self, rtype, TRUE));
|
||||
}
|
||||
|
||||
iface = nm_device_get_iface (device);
|
||||
g_assert (iface);
|
||||
|
||||
type_desc = nm_device_get_type_desc (device);
|
||||
g_assert (type_desc);
|
||||
driver = nm_device_get_driver (device);
|
||||
if (!driver)
|
||||
driver = "unknown";
|
||||
nm_log_info (LOGD_HW, "(%s): new %s device (carrier: %s, driver: '%s', ifindex: %d)",
|
||||
iface, type_desc,
|
||||
nm_device_has_capability (device, NM_DEVICE_CAP_CARRIER_DETECT)
|
||||
? (nm_device_has_carrier (device) ? "ON" : "OFF")
|
||||
: "UNKNOWN",
|
||||
driver, nm_device_get_ifindex (device));
|
||||
|
||||
nm_log_info (LOGD_HW, "(%s): new %s device", iface, type_desc);
|
||||
|
||||
unmanaged_specs = nm_settings_get_unmanaged_specs (priv->settings);
|
||||
user_unmanaged = nm_device_spec_match_list (device, unmanaged_specs);
|
||||
nm_device_set_unmanaged_initial (device, NM_UNMANAGED_USER, user_unmanaged);
|
||||
|
||||
sleeping = manager_sleeping (self);
|
||||
nm_device_set_unmanaged_initial (device, NM_UNMANAGED_INTERNAL, sleeping);
|
||||
nm_device_set_unmanaged_initial (device,
|
||||
NM_UNMANAGED_USER,
|
||||
nm_device_spec_match_list (device, unmanaged_specs));
|
||||
nm_device_set_unmanaged_initial (device,
|
||||
NM_UNMANAGED_INTERNAL,
|
||||
manager_sleeping (self));
|
||||
|
||||
dbus_path = nm_exported_object_export (NM_EXPORTED_OBJECT (device));
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): exported as %s", nm_device_get_iface (device), dbus_path);
|
||||
|
||||
nm_device_finish_init (device);
|
||||
|
||||
if (try_assume) {
|
||||
connection_assumed = recheck_assume_connection (device, self);
|
||||
g_signal_connect (device, NM_DEVICE_RECHECK_ASSUME,
|
||||
G_CALLBACK (recheck_assume_connection), self);
|
||||
}
|
||||
|
||||
if (!connection_assumed && nm_device_get_managed (device)) {
|
||||
nm_device_state_changed (device,
|
||||
NM_DEVICE_STATE_UNAVAILABLE,
|
||||
NM_DEVICE_STATE_REASON_NOW_MANAGED);
|
||||
}
|
||||
|
||||
/* Try to generate a default connection. If this fails because the link is
|
||||
* not initialized, we will retry again in device_link_initialized_cb().
|
||||
*/
|
||||
nm_settings_device_added (priv->settings, device);
|
||||
g_signal_emit (self, signals[DEVICE_ADDED], 0, device);
|
||||
g_object_notify (G_OBJECT (self), NM_MANAGER_DEVICES);
|
||||
@@ -1808,11 +1807,6 @@ add_device (NMManager *self, NMDevice *device, gboolean try_assume)
|
||||
if (d != device)
|
||||
nm_device_notify_new_device_added (d, device);
|
||||
}
|
||||
|
||||
/* New devices might be master interfaces for virtual interfaces; so we may
|
||||
* need to create new virtual interfaces now.
|
||||
*/
|
||||
system_create_virtual_devices (self);
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
@@ -1824,9 +1818,10 @@ factory_device_added_cb (NMDeviceFactory *factory,
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (nm_device_realize (device, NULL, &error))
|
||||
add_device (NM_MANAGER (user_data), device, TRUE);
|
||||
else {
|
||||
if (nm_device_realize (device, NULL, &error)) {
|
||||
add_device (NM_MANAGER (user_data), device);
|
||||
nm_device_setup_finish (device, NULL);
|
||||
} else {
|
||||
nm_log_warn (LOGD_DEVICE, "(%s): failed to realize device: %s",
|
||||
nm_device_get_iface (device), error->message);
|
||||
g_error_free (error);
|
||||
@@ -1881,6 +1876,26 @@ platform_link_added (NMManager *self,
|
||||
if (nm_manager_get_device_by_ifindex (self, ifindex))
|
||||
return;
|
||||
|
||||
device = find_device_by_iface (self, plink->name);
|
||||
if (device) {
|
||||
if (!nm_device_is_real (device)) {
|
||||
if (nm_device_realize (device, plink, &error))
|
||||
nm_device_setup_finish (device, plink);
|
||||
else {
|
||||
nm_log_warn (LOGD_DEVICE, "(%s): %s", plink->name, error->message);
|
||||
g_clear_error (&error);
|
||||
remove_device (self, device, FALSE, FALSE);
|
||||
}
|
||||
return;
|
||||
} else if (!nm_device_realize (device, plink, &error)) {
|
||||
nm_log_warn (LOGD_HW, "%s: factory failed to create device: %s",
|
||||
plink->name, error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Try registered device factories */
|
||||
factory = nm_device_factory_manager_find_factory_for_link_type (plink->type);
|
||||
if (factory) {
|
||||
@@ -1917,10 +1932,11 @@ platform_link_added (NMManager *self,
|
||||
if (device) {
|
||||
if (nm_plugin_missing)
|
||||
nm_device_set_nm_plugin_missing (device, TRUE);
|
||||
if (nm_device_realize (device, plink, &error))
|
||||
add_device (self, device, plink->type != NM_LINK_TYPE_LOOPBACK);
|
||||
else {
|
||||
nm_log_warn (LOGD_HW, "%s: failed to realize device: %s",
|
||||
if (nm_device_realize (device, plink, &error)) {
|
||||
add_device (self, device);
|
||||
nm_device_setup_finish (device, plink);
|
||||
} else {
|
||||
nm_log_warn (LOGD_DEVICE, "%s: failed to realize device: %s",
|
||||
plink->name, error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
@@ -1954,17 +1970,21 @@ _platform_link_cb_idle (PlatformLinkCbData *data)
|
||||
device = nm_manager_get_device_by_ifindex (self, data->ifindex);
|
||||
if (device) {
|
||||
if (nm_device_is_software (device)) {
|
||||
/* Software devices stick around until their connection is removed */
|
||||
if (!nm_device_unrealize (device, FALSE, &error)) {
|
||||
nm_log_warn (LOGD_DEVICE, "(%s): failed to unrealize: %s",
|
||||
nm_device_get_iface (device),
|
||||
error->message);
|
||||
nm_device_get_iface (device),
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
remove_device (self, device, FALSE, TRUE);
|
||||
}
|
||||
} else {
|
||||
/* Hardware devices always get removed when their kernel link is gone */
|
||||
remove_device (self, device, FALSE, TRUE);
|
||||
}
|
||||
remove_device (self, device, FALSE, TRUE);
|
||||
}
|
||||
g_object_remove_weak_pointer (G_OBJECT (self), (gpointer *) &data->self);
|
||||
}
|
||||
g_object_remove_weak_pointer (G_OBJECT (self), (gpointer *) &data->self);
|
||||
}
|
||||
g_slice_free (PlatformLinkCbData, data);
|
||||
return G_SOURCE_REMOVE;
|
||||
@@ -2079,7 +2099,8 @@ impl_manager_get_devices (NMManager *self,
|
||||
const char *path;
|
||||
|
||||
path = nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data));
|
||||
if (path)
|
||||
if ( path
|
||||
&& nm_device_is_real (iter->data))
|
||||
paths[i++] = path;
|
||||
}
|
||||
paths[i++] = NULL;
|
||||
@@ -2181,7 +2202,7 @@ find_master (NMManager *self,
|
||||
const char *master;
|
||||
NMDevice *master_device = NULL;
|
||||
NMSettingsConnection *master_connection = NULL;
|
||||
GSList *iter, *connections = NULL;
|
||||
GSList *iter;
|
||||
|
||||
s_con = nm_connection_get_setting_connection (connection);
|
||||
g_assert (s_con);
|
||||
@@ -2191,7 +2212,7 @@ find_master (NMManager *self,
|
||||
return TRUE; /* success, but no master */
|
||||
|
||||
/* Try as an interface name first */
|
||||
master_device = find_device_by_ip_iface (self, master);
|
||||
master_device = find_device_by_iface (self, master);
|
||||
if (master_device) {
|
||||
if (master_device == device) {
|
||||
g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_DEPENDENCY_FAILED,
|
||||
@@ -2223,23 +2244,6 @@ find_master (NMManager *self,
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Might be a virtual interface that hasn't been created yet, so
|
||||
* look through the interface names of connections that require
|
||||
* virtual interfaces and see if one of their virtual interface
|
||||
* names matches the master.
|
||||
*/
|
||||
connections = nm_manager_get_activatable_connections (self);
|
||||
for (iter = connections; iter && !master_connection; iter = g_slist_next (iter)) {
|
||||
NMSettingsConnection *candidate = iter->data;
|
||||
char *vname;
|
||||
|
||||
vname = get_virtual_iface_name (self, NM_CONNECTION (candidate), NULL, NULL);
|
||||
if (g_strcmp0 (master, vname) == 0 && is_compatible_with_slave (NM_CONNECTION (candidate), connection))
|
||||
master_connection = candidate;
|
||||
g_free (vname);
|
||||
}
|
||||
g_slist_free (connections);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2333,7 +2337,7 @@ ensure_master_active_connection (NMManager *self,
|
||||
/* If the device is disconnected, find a compatible connection and
|
||||
* activate it on the device.
|
||||
*/
|
||||
if (master_state == NM_DEVICE_STATE_DISCONNECTED) {
|
||||
if (master_state == NM_DEVICE_STATE_DISCONNECTED || !nm_device_is_real (master_device)) {
|
||||
GSList *connections;
|
||||
|
||||
g_assert (master_connection == NULL);
|
||||
@@ -2394,9 +2398,11 @@ ensure_master_active_connection (NMManager *self,
|
||||
continue;
|
||||
|
||||
found_device = TRUE;
|
||||
master_state = nm_device_get_state (candidate);
|
||||
if (master_state != NM_DEVICE_STATE_DISCONNECTED)
|
||||
continue;
|
||||
if (!nm_device_is_software (candidate)) {
|
||||
master_state = nm_device_get_state (candidate);
|
||||
if (nm_device_is_real (candidate) && master_state != NM_DEVICE_STATE_DISCONNECTED)
|
||||
continue;
|
||||
}
|
||||
|
||||
master_ac = nm_manager_activate_connection (self,
|
||||
master_connection,
|
||||
@@ -2683,6 +2689,17 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError *
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Create any backing resources the device needs */
|
||||
if (!nm_device_is_real (device)) {
|
||||
NMDevice *parent;
|
||||
|
||||
parent = find_parent_device_for_connection (self, (NMConnection *) connection);
|
||||
if (!nm_device_create_and_realize (device, (NMConnection *) connection, parent, error)) {
|
||||
g_prefix_error (error, "%s failed to create resources: ", nm_device_get_iface (device));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to find the master connection/device if the connection has a dependency */
|
||||
if (!find_master (self, applied, device,
|
||||
&master_connection, &master_device, &master_ac,
|
||||
@@ -3086,7 +3103,7 @@ validate_activation_request (NMManager *self,
|
||||
if (!iface)
|
||||
goto error;
|
||||
|
||||
device = find_device_by_ip_iface (self, iface);
|
||||
device = find_device_by_iface (self, iface);
|
||||
g_free (iface);
|
||||
}
|
||||
}
|
||||
@@ -4209,6 +4226,7 @@ gboolean
|
||||
nm_manager_start (NMManager *self, GError **error)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
GSList *iter, *connections;
|
||||
guint i;
|
||||
|
||||
if (!nm_settings_start (priv->settings, error))
|
||||
@@ -4256,11 +4274,14 @@ nm_manager_start (NMManager *self, GError **error)
|
||||
/* Load VPN plugins */
|
||||
priv->vpn_manager = g_object_ref (nm_vpn_manager_get ());
|
||||
|
||||
/*
|
||||
* Connections added before the manager is started do not emit
|
||||
/* Connections added before the manager is started do not emit
|
||||
* connection-added signals thus devices have to be created manually.
|
||||
*/
|
||||
system_create_virtual_devices (self);
|
||||
nm_log_dbg (LOGD_CORE, "creating virtual devices...");
|
||||
connections = nm_settings_get_connections (priv->settings);
|
||||
for (iter = connections; iter; iter = iter->next)
|
||||
connection_added (priv->settings, NM_CONNECTION (iter->data), self);
|
||||
g_slist_free (connections);
|
||||
|
||||
priv->devices_inited = TRUE;
|
||||
|
||||
@@ -5067,6 +5088,12 @@ nm_manager_init (NMManager *manager)
|
||||
priv->metered = NM_METERED_UNKNOWN;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
device_is_real (GObject *device, gpointer user_data)
|
||||
{
|
||||
return nm_device_is_real (NM_DEVICE (device));
|
||||
}
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
@@ -5139,7 +5166,7 @@ get_property (GObject *object, guint prop_id,
|
||||
g_value_set_boolean (value, priv->sleeping);
|
||||
break;
|
||||
case PROP_DEVICES:
|
||||
nm_utils_g_value_set_object_path_array (value, priv->devices, NULL, NULL);
|
||||
nm_utils_g_value_set_object_path_array (value, priv->devices, device_is_real, NULL);
|
||||
break;
|
||||
case PROP_METERED:
|
||||
g_value_set_uint (value, priv->metered);
|
||||
|
Reference in New Issue
Block a user