summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-09-05 08:50:02 -0500
committerDan Williams <dcbw@redhat.com>2015-07-31 14:06:09 -0500
commite8139f56c26ae3bcc5e14abdb29970ae07e93299 (patch)
tree202fe6b86700440bae1d4161c3daf49c34d4dd09
parentcf455aa0e20f16b109a4cd4e76e26bb4f698d97e (diff)
downloadNetworkManager-e8139f56c26ae3bcc5e14abdb29970ae07e93299.tar.gz
core: split device creation and device setup (bgo #737458)
Future patches will create devices long before they are backed by kernel resources, so we need to split NMDevice object creation from actual setup based on the backing resources. This patch combines the NMDeviceFactory's new_link() and create_virtual_device_for_connection() class methods into a single create_device() method that simply creates an unrealized NMDevice object; this method is not expected to fail unless the device is supposed to be ignored. This also means that the NMDevice 'platform-device' property is removed, because a platform link object may not be available at NMDevice object creation time. After the device is created, it is then "realized" at some later time from a platform link (for existing/hardware devices via the realize() method) or from an NMConnection (for newly created software devices via the create_and_realize() NMDeviceClass methods). https://bugzilla.gnome.org/show_bug.cgi?id=737458
-rw-r--r--src/devices/bluetooth/nm-bluez-manager.c8
-rw-r--r--src/devices/nm-device-bond.c66
-rw-r--r--src/devices/nm-device-bridge.c102
-rw-r--r--src/devices/nm-device-ethernet.c19
-rw-r--r--src/devices/nm-device-factory.c96
-rw-r--r--src/devices/nm-device-factory.h85
-rw-r--r--src/devices/nm-device-generic.c39
-rw-r--r--src/devices/nm-device-generic.h2
-rw-r--r--src/devices/nm-device-gre.c10
-rw-r--r--src/devices/nm-device-infiniband.c132
-rw-r--r--src/devices/nm-device-macvlan.c10
-rw-r--r--src/devices/nm-device-private.h2
-rw-r--r--src/devices/nm-device-tun.c76
-rw-r--r--src/devices/nm-device-veth.c10
-rw-r--r--src/devices/nm-device-vlan.c312
-rw-r--r--src/devices/nm-device-vlan.h3
-rw-r--r--src/devices/nm-device-vxlan.c29
-rw-r--r--src/devices/nm-device.c353
-rw-r--r--src/devices/nm-device.h61
-rw-r--r--src/devices/team/nm-device-team.c39
-rw-r--r--src/devices/team/nm-device-team.h14
-rw-r--r--src/devices/team/nm-team-factory.c20
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c6
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.h2
-rw-r--r--src/devices/wifi/nm-device-wifi.c15
-rw-r--r--src/devices/wifi/nm-device-wifi.h2
-rw-r--r--src/devices/wifi/nm-wifi-factory.c16
-rw-r--r--src/devices/wwan/nm-wwan-factory.c11
-rw-r--r--src/nm-manager.c30
29 files changed, 825 insertions, 745 deletions
diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c
index 8d41ca3f1b..ed424bd2f6 100644
--- a/src/devices/bluetooth/nm-bluez-manager.c
+++ b/src/devices/bluetooth/nm-bluez-manager.c
@@ -409,7 +409,11 @@ nm_bluez_manager_init (NMBluezManager *self)
}
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
g_warn_if_fail (plink->type == NM_LINK_TYPE_BNEP);
*out_ignore = TRUE;
@@ -420,7 +424,7 @@ static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
factory_iface->get_supported_types = get_supported_types;
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
factory_iface->start = start;
}
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index f00f618fa9..b352e513dd 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -464,6 +464,32 @@ release_slave (NMDevice *device,
return success;
}
+static gboolean
+create_and_realize (NMDevice *device,
+ NMConnection *connection,
+ NMDevice *parent,
+ NMPlatformLink *out_plink,
+ GError **error)
+{
+ const char *iface = nm_device_get_iface (device);
+ NMPlatformError plerr;
+
+ g_assert (iface);
+ g_assert (nm_device_get_ifindex (device) <= 0);
+ g_assert (out_plink);
+
+ plerr = nm_platform_bond_add (NM_PLATFORM_GET, iface, out_plink);
+ if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create bond interface '%s' for '%s': %s",
+ iface,
+ nm_connection_get_id (connection),
+ nm_platform_error_to_string (plerr));
+ return FALSE;
+ }
+ return TRUE;
+}
+
/******************************************************************/
static void
@@ -524,6 +550,7 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
parent_class->update_connection = update_connection;
parent_class->master_update_slave_connection = master_update_slave_connection;
+ parent_class->create_and_realize = create_and_realize;
parent_class->act_stage1_prepare = act_stage1_prepare;
parent_class->ip4_config_pre_commit = ip4_config_pre_commit;
parent_class->enslave_slave = enslave_slave;
@@ -547,38 +574,12 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
#define NM_BOND_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BOND_FACTORY, NMBondFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
-{
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_DRIVER, "bonding",
- NM_DEVICE_TYPE_DESC, "Bond",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
- NM_DEVICE_IS_MASTER, TRUE,
- NULL);
-}
-
-static NMDevice *
-create_virtual_device_for_connection (NMDeviceFactory *factory,
- NMConnection *connection,
- NMDevice *parent,
- GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
- const char *iface = nm_connection_get_interface_name (connection);
- NMPlatformError plerr;
-
- g_assert (iface);
-
- plerr = nm_platform_bond_add (NM_PLATFORM_GET, iface, NULL);
- if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
- g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "Failed to create bond interface '%s' for '%s': %s",
- iface,
- nm_connection_get_id (connection),
- nm_platform_error_to_string (plerr));
- return NULL;
- }
-
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
NM_DEVICE_IFACE, iface,
NM_DEVICE_DRIVER, "bonding",
@@ -591,7 +592,6 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (BOND, Bond, bond,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_BOND)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BOND_SETTING_NAME),
- factory_iface->new_link = new_link;
- factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
+ factory_iface->create_device = create_device;
)
diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c
index cce97875d7..b031a43e39 100644
--- a/src/devices/nm-device-bridge.c
+++ b/src/devices/nm-device-bridge.c
@@ -390,6 +390,52 @@ release_slave (NMDevice *device,
return success;
}
+static gboolean
+create_and_realize (NMDevice *device,
+ NMConnection *connection,
+ NMDevice *parent,
+ NMPlatformLink *out_plink,
+ GError **error)
+{
+ NMSettingBridge *s_bridge;
+ const char *iface = nm_device_get_iface (device);
+ const char *hwaddr;
+ guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX];
+ NMPlatformError plerr;
+
+ g_assert (iface);
+ g_assert (nm_device_get_ifindex (device) <= 0);
+ g_assert (out_plink);
+
+ s_bridge = nm_connection_get_setting_bridge (connection);
+ g_assert (s_bridge);
+ hwaddr = nm_setting_bridge_get_mac_address (s_bridge);
+ if (hwaddr) {
+ if (!nm_utils_hwaddr_aton (hwaddr, mac_address, ETH_ALEN)) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "Invalid hardware address '%s'",
+ hwaddr);
+ return FALSE;
+ }
+ }
+
+ plerr = nm_platform_bridge_add (NM_PLATFORM_GET,
+ iface,
+ hwaddr ? mac_address : NULL,
+ hwaddr ? ETH_ALEN : 0,
+ out_plink);
+ if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create bridge interface '%s' for '%s': %s",
+ iface,
+ nm_connection_get_id (connection),
+ nm_platform_error_to_string (plerr));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/******************************************************************/
static void
@@ -450,6 +496,7 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
parent_class->update_connection = update_connection;
parent_class->master_update_slave_connection = master_update_slave_connection;
+ parent_class->create_and_realize = create_and_realize;
parent_class->act_stage1_prepare = act_stage1_prepare;
parent_class->enslave_slave = enslave_slave;
parent_class->release_slave = release_slave;
@@ -472,54 +519,12 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass)
#define NM_BRIDGE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BRIDGE_FACTORY, NMBridgeFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
-{
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_DRIVER, "bridge",
- NM_DEVICE_TYPE_DESC, "Bridge",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE,
- NM_DEVICE_IS_MASTER, TRUE,
- NULL);
-}
-
-static NMDevice *
-create_virtual_device_for_connection (NMDeviceFactory *factory,
- NMConnection *connection,
- NMDevice *parent,
- GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
- const char *iface = nm_connection_get_interface_name (connection);
- NMSettingBridge *s_bridge;
- const char *mac_address_str;
- guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX];
- NMPlatformError plerr;
-
- g_assert (iface);
-
- s_bridge = nm_connection_get_setting_bridge (connection);
- g_assert (s_bridge);
-
- mac_address_str = nm_setting_bridge_get_mac_address (s_bridge);
- if (mac_address_str) {
- if (!nm_utils_hwaddr_aton (mac_address_str, mac_address, ETH_ALEN))
- mac_address_str = NULL;
- }
-
- plerr = nm_platform_bridge_add (NM_PLATFORM_GET,
- iface,
- mac_address_str ? mac_address : NULL,
- mac_address_str ? ETH_ALEN : 0,
- NULL);
- if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
- g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "Failed to create bridge interface '%s' for '%s': %s",
- iface,
- nm_connection_get_id (connection),
- nm_platform_error_to_string (plerr));
- return NULL;
- }
-
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE,
NM_DEVICE_IFACE, iface,
NM_DEVICE_DRIVER, "bridge",
@@ -532,7 +537,6 @@ create_virtual_device_for_connection (NMDeviceFactory *factory,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (BRIDGE, Bridge, bridge,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_BRIDGE)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BRIDGE_SETTING_NAME),
- factory_iface->new_link = new_link;
- factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
+ factory_iface->create_device = create_device;
)
diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c
index 8fcf4827fb..6caea4974c 100644
--- a/src/devices/nm-device-ethernet.c
+++ b/src/devices/nm-device-ethernet.c
@@ -299,6 +299,14 @@ nm_device_ethernet_init (NMDeviceEthernet *self)
priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
+static void
+setup (NMDevice *device, NMPlatformLink *plink)
+{
+ NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->setup (device, plink);
+
+ g_object_notify (G_OBJECT (device), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS);
+}
+
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *device)
{
@@ -1674,6 +1682,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->check_connection_compatible = check_connection_compatible;
parent_class->complete_connection = complete_connection;
parent_class->new_default_connection = new_default_connection;
@@ -1715,10 +1724,14 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
#define NM_ETHERNET_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ETHERNET_FACTORY, NMEthernetFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET,
- NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "Ethernet",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
NULL);
@@ -1727,6 +1740,6 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (ETHERNET, Ethernet, ethernet,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_ETHERNET)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_PPPOE_SETTING_NAME),
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
)
diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c
index 1303480857..7f2468bd0d 100644
--- a/src/devices/nm-device-factory.c
+++ b/src/devices/nm-device-factory.c
@@ -79,86 +79,64 @@ nm_device_factory_start (NMDeviceFactory *factory)
}
NMDevice *
-nm_device_factory_new_link (NMDeviceFactory *factory,
- NMPlatformLink *plink,
- gboolean *out_ignore,
- GError **error)
+nm_device_factory_create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore,
+ GError **error)
{
NMDeviceFactory *interface;
const NMLinkType *link_types = NULL;
const char **setting_types = NULL;
int i;
- g_return_val_if_fail (factory != NULL, NULL);
- g_return_val_if_fail (plink != NULL, NULL);
+ g_return_val_if_fail (factory, NULL);
+ g_return_val_if_fail (iface && *iface, NULL);
+ g_return_val_if_fail (plink || connection, NULL);
+ g_return_val_if_fail (!plink || !connection, NULL);
- /* Ensure the factory can create interfaces for this connection */
nm_device_factory_get_supported_types (factory, &link_types, &setting_types);
- for (i = 0; link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
- if (plink->type == link_types[i])
- break;
- }
-
- if (link_types[i] == NM_LINK_TYPE_UNKNOWN) {
- g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "Device factory %s does not support link type %s (%d)",
- G_OBJECT_TYPE_NAME (factory),
- plink->kind, plink->type);
- return NULL;
- }
-
- interface = NM_DEVICE_FACTORY_GET_INTERFACE (factory);
- if (!interface->new_link) {
- g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
- "Device factory %s cannot manage new devices",
- G_OBJECT_TYPE_NAME (factory));
- return NULL;
- }
- return interface->new_link (factory, plink, out_ignore, error);
-}
+ if (plink) {
+ g_return_val_if_fail (strcmp (iface, plink->name) == 0, NULL);
-NMDevice *
-nm_device_factory_create_virtual_device_for_connection (NMDeviceFactory *factory,
- NMConnection *connection,
- NMDevice *parent,
- GError **error)
-{
- NMDeviceFactory *interface;
- const char **setting_types = NULL;
- gboolean found = FALSE;
- int i;
+ for (i = 0; link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) {
+ if (plink->type == link_types[i])
+ break;
+ }
- g_return_val_if_fail (factory, NULL);
- g_return_val_if_fail (connection, NULL);
- g_return_val_if_fail (!error || !*error, NULL);
-
- /* Ensure the factory can create interfaces for this connection */
- nm_device_factory_get_supported_types (factory, NULL, &setting_types);
- for (i = 0; setting_types && setting_types[i]; i++) {
- if (nm_connection_is_type (connection, setting_types[i])) {
- found = TRUE;
- break;
+ if (link_types[i] == NM_LINK_TYPE_UNKNOWN) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Device factory %s does not support link type %s (%d)",
+ G_OBJECT_TYPE_NAME (factory),
+ plink->kind, plink->type);
+ return NULL;
+ }
+ } else if (connection) {
+ for (i = 0; setting_types && setting_types[i]; i++) {
+ if (nm_connection_is_type (connection, setting_types[i]))
+ break;
}
- }
- if (!found) {
- g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
- "Device factory %s does not support connection type %s",
- G_OBJECT_TYPE_NAME (factory),
- nm_connection_get_connection_type (connection));
- return NULL;
+ if (!setting_types[i]) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
+ "Device factory %s does not support connection type %s",
+ G_OBJECT_TYPE_NAME (factory),
+ nm_connection_get_connection_type (connection));
+ return NULL;
+ }
}
interface = NM_DEVICE_FACTORY_GET_INTERFACE (factory);
- if (!interface->create_virtual_device_for_connection) {
+ if (!interface->create_device) {
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
- "Device factory %s cannot create virtual devices",
+ "Device factory %s cannot manage new devices",
G_OBJECT_TYPE_NAME (factory));
return NULL;
}
- return interface->create_virtual_device_for_connection (factory, connection, parent, error);
+ return interface->create_device (factory, iface, plink, connection, out_ignore);
}
const char *
diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h
index 1ac1fc9a41..1bee6b76cb 100644
--- a/src/devices/nm-device-factory.h
+++ b/src/devices/nm-device-factory.h
@@ -84,51 +84,7 @@ struct _NMDeviceFactory {
* Start the factory and discover any existing devices that the factory
* can manage.
*/
- void (*start) (NMDeviceFactory *factory);
-
- /**
- * new_link:
- * @factory: the #NMDeviceFactory
- * @plink: the new link
- * @out_ignore: on return, %TRUE if the link should be ignored
- * @error: error if the link could be claimed but an error occurred
- *
- * The NetworkManager core was notified of a new link which the plugin
- * may want to claim and create a #NMDevice subclass for. If the link
- * represents a device which the factory does not support, or the link
- * is supported but the device could not be created, %NULL should be
- * returned and @error should be set.
- *
- * If the plugin cannot create a #NMDevice for the link and wants the
- * core to ignore it, set @out_ignore to %TRUE and return no error.
- *
- * @plink is guaranteed to be one of the types the factory returns in
- * get_supported_types().
- *
- * Returns: the #NMDevice if the link was claimed and created, %NULL if not
- */
- NMDevice * (*new_link) (NMDeviceFactory *factory,
- NMPlatformLink *plink,
- gboolean *out_ignore,
- GError **error);
-
- /**
- * create_virtual_device_for_connection:
- * @factory: the #NMDeviceFactory
- * @connection: the #NMConnection
- * @error: a @GError in case of failure
- *
- * Virtual device types (such as team, bond, bridge) may need to be created.
- * This function tries to create a device based on the given @connection.
- *
- * Returns: the newly created #NMDevice. If the factory does not support the
- * connection type, it should return %NULL and leave @error unset. On error
- * it should set @error and return %NULL.
- */
- NMDevice * (*create_virtual_device_for_connection) (NMDeviceFactory *factory,
- NMConnection *connection,
- NMDevice *parent,
- GError **error);
+ void (*start) (NMDeviceFactory *factory);
/**
* get_connection_parent:
@@ -159,6 +115,30 @@ struct _NMDeviceFactory {
NMConnection *connection,
const char *parent_iface);
+ /**
+ * create_device:
+ * @factory: the #NMDeviceFactory
+ * @iface: the interface name of the device
+ * @plink: the #NMPlatformLink if backed by a kernel device
+ * @connection: the #NMConnection if not backed by a kernel device
+ * @out_ignore: on return, %TRUE if the link should be ignored
+ *
+ * The plugin should create a new unrealized device using the details given
+ * by @iface and @plink or @connection. If both @iface and @plink are given,
+ * they are guaranteed to match. If both @iface and @connection are given,
+ * @iface is guaranteed to be the interface name that @connection specifies.
+ *
+ * If the plugin cannot create a #NMDevice for the link and wants the
+ * core to ignore it, set @out_ignore to %TRUE and return %NULL.
+ *
+ * Returns: the new unrealized #NMDevice, or %NULL
+ */
+ NMDevice * (*create_device) (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore);
+
/* Signals */
/**
@@ -201,15 +181,12 @@ char * nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory,
void nm_device_factory_start (NMDeviceFactory *factory);
-NMDevice * nm_device_factory_new_link (NMDeviceFactory *factory,
- NMPlatformLink *plink,
- gboolean *out_ignore,
- GError **error);
-
-NMDevice * nm_device_factory_create_virtual_device_for_connection (NMDeviceFactory *factory,
- NMConnection *connection,
- NMDevice *parent,
- GError **error);
+NMDevice * nm_device_factory_create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore,
+ GError **error);
/* For use by implementations */
gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory,
diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c
index db5b2b6b4d..5d092b98f7 100644
--- a/src/devices/nm-device-generic.c
+++ b/src/devices/nm-device-generic.c
@@ -60,6 +60,21 @@ get_type_description (NMDevice *device)
return NM_DEVICE_CLASS (nm_device_generic_parent_class)->get_type_description (device);
}
+static void
+setup (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);
+
+ g_clear_pointer (&priv->type_description, g_free);
+ ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self));
+ if (ifindex > 0)
+ priv->type_description = g_strdup (nm_platform_link_get_type_name (NM_PLATFORM_GET, ifindex));
+}
+
static gboolean
check_connection_compatible (NMDevice *device, NMConnection *connection)
{
@@ -96,12 +111,12 @@ update_connection (NMDevice *device, NMConnection *connection)
/**************************************************************/
NMDevice *
-nm_device_generic_new (NMPlatformLink *platform_device)
+nm_device_generic_new (NMPlatformLink *plink)
{
- g_return_val_if_fail (platform_device != NULL, NULL);
+ g_return_val_if_fail (plink != NULL, NULL);
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GENERIC,
- NM_DEVICE_PLATFORM_DEVICE, platform_device,
+ NM_DEVICE_IFACE, plink->name,
NM_DEVICE_TYPE_DESC, "Generic",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
NULL);
@@ -114,22 +129,6 @@ nm_device_generic_init (NMDeviceGeneric *self)
}
static void
-constructed (GObject *object)
-{
- NMDeviceGeneric *self = NM_DEVICE_GENERIC (object);
- NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self);
-
- if (!priv->type_description) {
- int ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self));
-
- if (ifindex != 0)
- priv->type_description = g_strdup (nm_platform_link_get_type_name (NM_PLATFORM_GET, ifindex));
- }
-
- G_OBJECT_CLASS (nm_device_generic_parent_class)->constructed (object);
-}
-
-static void
dispose (GObject *object)
{
NMDeviceGeneric *self = NM_DEVICE_GENERIC (object);
@@ -184,11 +183,11 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass)
parent_class->connection_type = NM_SETTING_GENERIC_SETTING_NAME;
- object_class->constructed = constructed;
object_class->dispose = dispose;
object_class->get_property = get_property;
object_class->set_property = set_property;
+ parent_class->setup = setup;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->get_type_description = get_type_description;
parent_class->check_connection_compatible = check_connection_compatible;
diff --git a/src/devices/nm-device-generic.h b/src/devices/nm-device-generic.h
index 4dad4421f0..1b3fa7f9bc 100644
--- a/src/devices/nm-device-generic.h
+++ b/src/devices/nm-device-generic.h
@@ -45,7 +45,7 @@ typedef struct {
GType nm_device_generic_get_type (void);
-NMDevice *nm_device_generic_new (NMPlatformLink *platform_device);
+NMDevice *nm_device_generic_new (NMPlatformLink *plink);
G_END_DECLS
diff --git a/src/devices/nm-device-gre.c b/src/devices/nm-device-gre.c
index 9cda059603..47169897be 100644
--- a/src/devices/nm-device-gre.c
+++ b/src/devices/nm-device-gre.c
@@ -265,10 +265,14 @@ nm_device_gre_class_init (NMDeviceGreClass *klass)
#define NM_GRE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_GRE_FACTORY, NMGreFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GRE,
- NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "Gre",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
NULL);
@@ -276,6 +280,6 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (GRE, Gre, gre,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP),
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
)
diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c
index 98e2f1de09..ce531655bc 100644
--- a/src/devices/nm-device-infiniband.c
+++ b/src/devices/nm-device-infiniband.c
@@ -55,10 +55,7 @@ enum {
LAST_PROP
};
-static void
-nm_device_infiniband_init (NMDeviceInfiniband * self)
-{
-}
+/*************************************************************/
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *dev)
@@ -238,6 +235,66 @@ update_connection (NMDevice *device, NMConnection *connection)
g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_TRANSPORT_MODE, transport_mode, NULL);
}
+static gboolean
+create_and_realize (NMDevice *device,
+ NMConnection *connection,
+ NMDevice *parent,
+ NMPlatformLink *out_plink,
+ GError **error)
+{
+ NMSettingInfiniband *s_infiniband;
+ int parent_ifindex, p_key;
+ NMPlatformError plerr;
+
+ g_assert (nm_device_get_ifindex (device) <= 0);
+ g_assert (out_plink);
+
+ if (!NM_IS_DEVICE_INFINIBAND (parent)) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Parent interface %s must be an InfiniBand interface",
+ nm_device_get_iface (parent));
+ return FALSE;
+ }
+
+ s_infiniband = nm_connection_get_setting_infiniband (connection);
+
+ /* Can only create partitions at this time */
+ p_key = nm_setting_infiniband_get_p_key (s_infiniband);
+ if (p_key < 0) {
+ g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "only InfiniBand partitions can be created");
+ return FALSE;
+ }
+
+ parent_ifindex = nm_device_get_ifindex (parent);
+ if (parent_ifindex <= 0) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "failed to get InfiniBand parent %s ifindex",
+ nm_device_get_iface (parent));
+ return FALSE;
+ }
+
+ plerr = nm_platform_infiniband_partition_add (NM_PLATFORM_GET, parent_ifindex, p_key, out_plink);
+ if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create InfiniBand P_Key interface '%s' for '%s': %s",
+ nm_device_get_iface (device),
+ nm_connection_get_id (connection),
+ nm_platform_error_to_string (plerr));
+ return FALSE;
+ }
+
+ NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->is_partition = TRUE;
+ return TRUE;
+}
+
+/*************************************************************/
+
+static void
+nm_device_infiniband_init (NMDeviceInfiniband * self)
+{
+}
+
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
@@ -278,6 +335,7 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
object_class->get_property = get_property;
object_class->set_property = set_property;
+ parent_class->create_and_realize = create_and_realize;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->check_connection_compatible = check_connection_compatible;
parent_class->complete_connection = complete_connection;
@@ -304,58 +362,31 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass)
#define NM_INFINIBAND_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_INFINIBAND_FACTORY, NMInfinibandFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
-{
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_TYPE_DESC, "InfiniBand",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND,
- NM_DEVICE_INFINIBAND_IS_PARTITION, (plink->parent > 0),
- NULL);
-}
-
-static NMDevice *
-create_virtual_device_for_connection (NMDeviceFactory *factory,
- NMConnection *connection,
- NMDevice *parent,
- GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
- NMSettingInfiniband *s_infiniband;
- int p_key, parent_ifindex;
- const char *iface;
- NMPlatformError plerr;
-
- if (!NM_IS_DEVICE_INFINIBAND (parent)) {
- g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "Parent interface %s must be an InfiniBand interface",
- nm_device_get_iface (parent));
- return NULL;
- }
-
- s_infiniband = nm_connection_get_setting_infiniband (connection);
-
- iface = nm_setting_infiniband_get_virtual_interface_name (s_infiniband);
- g_assert (iface);
-
- parent_ifindex = nm_device_get_ifindex (parent);
- p_key = nm_setting_infiniband_get_p_key (s_infiniband);
-
- plerr = nm_platform_infiniband_partition_add (NM_PLATFORM_GET, parent_ifindex, p_key, NULL);
- if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
- g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "Failed to create InfiniBand P_Key interface '%s' for '%s': %s",
- iface,
- nm_connection_get_id (connection),
- nm_platform_error_to_string (plerr));
- return NULL;
+ gboolean is_partition = FALSE;
+
+ if (plink)
+ is_partition = (plink->parent > 0);
+ else if (connection) {
+ NMSettingInfiniband *s_infiniband;
+
+ s_infiniband = nm_connection_get_setting_infiniband (connection);
+ g_return_val_if_fail (s_infiniband, NULL);
+ is_partition = !!nm_setting_infiniband_get_parent (s_infiniband)
+ || ( nm_setting_infiniband_get_p_key (s_infiniband) >= 0
+ && nm_setting_infiniband_get_mac_address (s_infiniband));
}
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND,
NM_DEVICE_IFACE, iface,
- NM_DEVICE_DRIVER, nm_device_get_driver (parent),
NM_DEVICE_TYPE_DESC, "InfiniBand",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND,
- NM_DEVICE_INFINIBAND_IS_PARTITION, TRUE,
+ NM_DEVICE_INFINIBAND_IS_PARTITION, is_partition,
NULL);
}
@@ -395,8 +426,7 @@ get_virtual_iface_name (NMDeviceFactory *factory,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (INFINIBAND, Infiniband, infiniband,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_INFINIBAND)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_INFINIBAND_SETTING_NAME),
- factory_iface->new_link = new_link;
- factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
+ factory_iface->create_device = create_device;
factory_iface->get_connection_parent = get_connection_parent;
factory_iface->get_virtual_iface_name = get_virtual_iface_name;
)
diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c
index e2d256671e..51d75b5bc9 100644
--- a/src/devices/nm-device-macvlan.c
+++ b/src/devices/nm-device-macvlan.c
@@ -173,10 +173,14 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass)
#define NM_MACVLAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MACVLAN_FACTORY, NMMacvlanFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_MACVLAN,
- NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "Macvlan",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
NULL);
@@ -184,6 +188,6 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (MACVLAN, Macvlan, macvlan,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP),
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
)
diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
index 19e00e01cb..c4e3fe0de3 100644
--- a/src/devices/nm-device-private.h
+++ b/src/devices/nm-device-private.h
@@ -28,8 +28,6 @@
/* This file should only be used by subclasses of NMDevice */
-#define NM_DEVICE_PLATFORM_DEVICE "platform-device"
-
enum NMActStageReturn {
NM_ACT_STAGE_RETURN_FAILURE = 0,
NM_ACT_STAGE_RETURN_SUCCESS, /* Activation stage done */
diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c
index d996470af5..e2af6b279f 100644
--- a/src/devices/nm-device-tun.c
+++ b/src/devices/nm-device-tun.c
@@ -41,7 +41,6 @@ G_DEFINE_TYPE (NMDeviceTun, nm_device_tun, NM_TYPE_DEVICE_GENERIC)
typedef struct {
NMPlatformTunProperties props;
const char *mode;
- guint delay_tun_get_properties_id;
} NMDeviceTunPrivate;
enum {
@@ -95,17 +94,24 @@ link_changed (NMDevice *device, NMPlatformLink *info)
reload_tun_properties (NM_DEVICE_TUN (device));
}
-static gboolean
-delay_tun_get_properties_cb (gpointer user_data)
+static void
+setup (NMDevice *device, NMPlatformLink *plink)
{
- NMDeviceTun *self = user_data;
+ NMDeviceTun *self = NM_DEVICE_TUN (device);
NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self);
- priv->delay_tun_get_properties_id = 0;
+ NM_DEVICE_CLASS (nm_device_tun_parent_class)->setup (device, plink);
- reload_tun_properties (self);
+ priv->mode = NULL;
+ if (plink->type == NM_LINK_TYPE_TUN)
+ priv->mode = "tun";
+ else if (plink->type == NM_LINK_TYPE_TAP)
+ priv->mode = "tap";
+ else
+ g_assert_not_reached ();
+ g_object_notify (G_OBJECT (device), NM_DEVICE_TUN_MODE);
- return G_SOURCE_REMOVE;
+ reload_tun_properties (NM_DEVICE_TUN (device));
}
/**************************************************************/
@@ -116,37 +122,6 @@ nm_device_tun_init (NMDeviceTun *self)
}
static void
-constructed (GObject *object)
-{
- NMDeviceTun *self = NM_DEVICE_TUN (object);
- gboolean properties_read;
- NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self);
-
- properties_read = nm_platform_tun_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (self)), &priv->props);
-
- G_OBJECT_CLASS (nm_device_tun_parent_class)->constructed (object);
-
- if (!properties_read) {
- /* Error reading the tun properties. Maybe this was due to a race. Try again a bit later. */
- _LOGD (LOGD_HW, "could not read tun properties (retry)");
- priv->delay_tun_get_properties_id = g_timeout_add_seconds (1, delay_tun_get_properties_cb, self);
- }
-}
-
-static void
-dispose (GObject *object)
-{
- NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (object);
-
- if (priv->delay_tun_get_properties_id) {
- g_source_remove (priv->delay_tun_get_properties_id);
- priv->delay_tun_get_properties_id = 0;
- }
-
- G_OBJECT_CLASS (nm_device_tun_parent_class)->dispose (object);
-}
-
-static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
@@ -213,12 +188,11 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceTunPrivate));
- object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->set_property = set_property;
- object_class->dispose = dispose;
device_class->link_changed = link_changed;
+ device_class->setup = setup;
/* properties */
g_object_class_install_property
@@ -268,29 +242,21 @@ nm_device_tun_class_init (NMDeviceTunClass *klass)
#define NM_TUN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_TUN_FACTORY, NMTunFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
- const char *mode = NULL;
-
- if (plink->type == NM_LINK_TYPE_TUN)
- mode = "tun";
- else if (plink->type == NM_LINK_TYPE_TAP)
- mode = "tap";
- else {
- g_warn_if_reached ();
- mode = "unknown";
- }
-
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TUN,
- NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "Tun",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
- NM_DEVICE_TUN_MODE, mode,
NULL);
}
NM_DEVICE_FACTORY_DEFINE_INTERNAL (TUN, Tun, tun,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP),
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
)
diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c
index 944e9da616..1a3a65443d 100644
--- a/src/devices/nm-device-veth.c
+++ b/src/devices/nm-device-veth.c
@@ -175,10 +175,14 @@ nm_device_veth_class_init (NMDeviceVethClass *klass)
#define NM_VETH_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VETH_FACTORY, NMVethFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VETH,
- NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "Veth",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET,
NULL);
@@ -186,6 +190,6 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (VETH, Veth, veth,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VETH),
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
)
diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c
index 511656ffe0..d89bf625b5 100644
--- a/src/devices/nm-device-vlan.c
+++ b/src/devices/nm-device-vlan.c
@@ -51,8 +51,6 @@ G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE)
#define NM_DEVICE_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VLAN, NMDeviceVlanPrivate))
typedef struct {
- gboolean invalid;
-
NMDevice *parent;
guint parent_state_id;
int vlan_id;
@@ -63,8 +61,6 @@ enum {
PROP_PARENT,
PROP_VLAN_ID,
- PROP_INT_PARENT_DEVICE,
-
LAST_PROP
};
@@ -87,7 +83,7 @@ parent_state_changed (NMDevice *parent,
}
static void
-nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean construct)
+nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent)
{
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
NMDevice *device = NM_DEVICE (self);
@@ -109,16 +105,10 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr
device);
/* Set parent-dependent unmanaged flag */
- if (construct) {
- nm_device_set_initial_unmanaged_flag (device,
- NM_UNMANAGED_PARENT,
- !nm_device_get_managed (parent));
- } else {
- nm_device_set_unmanaged (device,
- NM_UNMANAGED_PARENT,
- !nm_device_get_managed (parent),
- NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
- }
+ nm_device_set_unmanaged (device,
+ NM_UNMANAGED_PARENT,
+ !nm_device_get_managed (parent),
+ NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED);
}
/* Recheck availability now that the parent has changed */
@@ -128,6 +118,112 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr
g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_PARENT);
}
+static void
+setup (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);
+
+ _LOGI (LOGD_HW | LOGD_VLAN, "VLAN ID %d with parent %s",
+ priv->vlan_id, nm_device_get_iface (priv->parent));
+}
+
+static gboolean
+realize (NMDevice *device,
+ NMPlatformLink *plink,
+ GError **error)
+{
+ NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
+ int parent_ifindex = -1, vlan_id = -1;
+ NMDevice *parent;
+
+ g_return_val_if_fail (plink, FALSE);
+
+ g_assert (plink->type == NM_LINK_TYPE_VLAN);
+
+ if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, plink->ifindex, &parent_ifindex, &vlan_id)) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "(%s): failed to read VLAN properties", plink->name);
+ return FALSE;
+ }
+
+ if (vlan_id < 0) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "(%s): VLAN ID invalid", plink->name);
+ return FALSE;
+ }
+
+ parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex);
+ if (!parent) {
+ nm_log_dbg (LOGD_HW, "(%s): VLAN parent interface unknown", plink->name);
+ return FALSE;
+ }
+
+ g_warn_if_fail (priv->parent == NULL);
+ nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent);
+ priv->vlan_id = vlan_id;
+
+ return TRUE;
+}
+
+static gboolean
+create_and_realize (NMDevice *device,
+ NMConnection *connection,
+ NMDevice *parent,
+ NMPlatformLink *out_plink,
+ GError **error)
+{
+ NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device);
+ const char *iface = nm_device_get_iface (device);
+ NMSettingVlan *s_vlan;
+ int parent_ifindex, vlan_id;
+ NMPlatformError plerr;
+
+ g_assert (nm_device_get_ifindex (device) <= 0);
+ g_assert (out_plink);
+
+ s_vlan = nm_connection_get_setting_vlan (connection);
+ g_assert (s_vlan);
+
+ if (!nm_device_supports_vlans (parent)) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED,
+ "no support for VLANs on interface %s of type %s",
+ nm_device_get_iface (parent),
+ nm_device_get_type_desc (parent));
+ return FALSE;
+ }
+
+ parent_ifindex = nm_device_get_ifindex (parent);
+ g_warn_if_fail (parent_ifindex > 0);
+
+ vlan_id = nm_setting_vlan_get_id (s_vlan);
+
+ plerr = nm_platform_vlan_add (NM_PLATFORM_GET,
+ iface,
+ parent_ifindex,
+ vlan_id,
+ nm_setting_vlan_get_flags (s_vlan),
+ out_plink);
+ if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
+ g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
+ "Failed to create VLAN interface '%s' for '%s': %s",
+ iface,
+ nm_connection_get_id (connection),
+ nm_platform_error_to_string (plerr));
+ return FALSE;
+ }
+
+ g_warn_if_fail (priv->parent == NULL);
+ nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent);
+ priv->vlan_id = vlan_id;
+
+ return TRUE;
+}
+
+/******************************************************************/
+
static NMDeviceCapabilities
get_generic_capabilities (NMDevice *dev)
{
@@ -183,7 +279,7 @@ component_added (NMDevice *device, GObject *component)
if (nm_device_get_ifindex (added_device) != parent_ifindex)
return FALSE;
- nm_device_vlan_set_parent (self, added_device, FALSE);
+ nm_device_vlan_set_parent (self, added_device);
/* Don't claim parent exclusively */
return FALSE;
@@ -357,7 +453,7 @@ update_connection (NMDevice *device, NMConnection *connection)
parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex);
g_assert (parent);
- nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent, FALSE);
+ nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent);
/* Update parent in the connection; default to parent's interface name */
new_parent = nm_device_get_iface (parent);
@@ -459,54 +555,6 @@ nm_device_vlan_init (NMDeviceVlan * self)
}
static void
-constructed (GObject *object)
-{
- NMDeviceVlan *self = NM_DEVICE_VLAN (object);
- NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
- int ifindex = nm_device_get_ifindex (NM_DEVICE (self));
- int parent_ifindex = -1, itype;
- int vlan_id;
-
- if (G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed)
- G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed (object);
-
- itype = nm_platform_link_get_type (NM_PLATFORM_GET, ifindex);
- if (itype != NM_LINK_TYPE_VLAN) {
- _LOGE (LOGD_VLAN, "failed to get VLAN interface type.");
- priv->invalid = TRUE;
- return;
- }
-
- if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, ifindex, &parent_ifindex, &vlan_id)) {
- _LOGW (LOGD_VLAN, "failed to get VLAN interface info.");
- priv->invalid = TRUE;
- return;
- }
-
- if (parent_ifindex < 0 || vlan_id < 0) {
- _LOGW (LOGD_VLAN, "VLAN parent ifindex (%d) or VLAN ID (%d) invalid.",
- parent_ifindex, priv->vlan_id);
- priv->invalid = TRUE;
- return;
- }
-
- if (priv->parent && parent_ifindex != nm_device_get_ip_ifindex (priv->parent)) {
- _LOGW (LOGD_VLAN, "VLAN parent %s (%d) and parent ifindex %d don't match.",
- nm_device_get_iface (priv->parent),
- nm_device_get_ifindex (priv->parent),
- parent_ifindex);
- priv->invalid = TRUE;
- return;
- }
-
- priv->vlan_id = vlan_id;
- _LOGI (LOGD_HW | LOGD_VLAN, "VLAN ID %d with parent %s (%d)",
- priv->vlan_id,
- priv->parent ? nm_device_get_iface (priv->parent) : "unknown",
- parent_ifindex);
-}
-
-static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
@@ -516,9 +564,6 @@ get_property (GObject *object, guint prop_id,
case PROP_PARENT:
nm_utils_g_value_set_object_path (value, priv->parent);
break;
- case PROP_INT_PARENT_DEVICE:
- g_value_set_object (value, priv->parent);
- break;
case PROP_VLAN_ID:
g_value_set_uint (value, priv->vlan_id);
break;
@@ -532,25 +577,13 @@ static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
- NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object);
-
- switch (prop_id) {
- case PROP_INT_PARENT_DEVICE:
- nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), g_value_get_object (value), TRUE);
- break;
- case PROP_VLAN_ID:
- priv->vlan_id = g_value_get_uint (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
static void
dispose (GObject *object)
{
- nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), NULL, FALSE);
+ nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), NULL);
G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object);
}
@@ -566,11 +599,13 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
g_type_class_add_private (object_class, sizeof (NMDeviceVlanPrivate));
/* virtual methods */
- object_class->constructed = constructed;
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->dispose = dispose;
+ parent_class->create_and_realize = create_and_realize;
+ parent_class->realize = realize;
+ parent_class->setup = setup;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->bring_up = bring_up;
parent_class->act_stage1_prepare = act_stage1_prepare;
@@ -594,16 +629,7 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
(object_class, PROP_VLAN_ID,
g_param_spec_uint (NM_DEVICE_VLAN_ID, "", "",
0, 4095, 0,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- /* Internal properties */
- g_object_class_install_property
- (object_class, PROP_INT_PARENT_DEVICE,
- g_param_spec_object (NM_DEVICE_VLAN_INT_PARENT_DEVICE, "", "",
- NM_TYPE_DEVICE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
&dbus_glib_nm_device_vlan_object_info);
@@ -615,93 +641,18 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass)
#define NM_VLAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VLAN_FACTORY, NMVlanFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
-{
- int parent_ifindex = -1;
- NMDevice *parent, *device;
-
- /* Find the parent device */
- if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, plink->ifindex, &parent_ifindex, NULL)) {
- g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "VLAN parent ifindex unknown");
- return NULL;
- }
- parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex);
-
- device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN,
- NM_DEVICE_PLATFORM_DEVICE, plink,
- NM_DEVICE_VLAN_INT_PARENT_DEVICE, parent,
- NM_DEVICE_DRIVER, "8021q",
- NM_DEVICE_TYPE_DESC, "VLAN",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN,
- NULL);
- if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) {
- g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "VLAN initialization failed");
- g_object_unref (device);
- device = NULL;
- }
-
- return device;
-}
-
-static NMDevice *
-create_virtual_device_for_connection (NMDeviceFactory *factory,
- NMConnection *connection,
- NMDevice *parent,
- GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
- NMDevice *device;
- NMSettingVlan *s_vlan;
- gs_free char *iface = NULL;
- NMPlatformError plerr;
-
- if (!NM_IS_DEVICE (parent)) {
- g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "VLAN interfaces must have parents");
- return NULL;
- }
-
- s_vlan = nm_connection_get_setting_vlan (connection);
- g_assert (s_vlan);
-
- iface = g_strdup (nm_connection_get_interface_name (connection));
- if (!iface) {
- iface = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent),
- nm_setting_vlan_get_id (s_vlan));
- }
-
- plerr = nm_platform_vlan_add (NM_PLATFORM_GET,
- iface,
- nm_device_get_ifindex (parent),
- nm_setting_vlan_get_id (s_vlan),
- nm_setting_vlan_get_flags (s_vlan),
- NULL);
- if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
- g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "Failed to create VLAN interface '%s' for '%s': %s",
- iface,
- nm_connection_get_id (connection),
- nm_platform_error_to_string (plerr));
- return NULL;
- }
-
- device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN,
- NM_DEVICE_IFACE, iface,
- NM_DEVICE_VLAN_INT_PARENT_DEVICE, parent,
- NM_DEVICE_DRIVER, "8021q",
- NM_DEVICE_TYPE_DESC, "VLAN",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN,
- NULL);
- if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) {
- g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
- "Failed to create VLAN interface '%s' for '%s': initialization failed",
- iface, nm_connection_get_id (connection));
- g_object_unref (device);
- device = NULL;
- }
-
- return device;
+ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN,
+ NM_DEVICE_IFACE, iface,
+ NM_DEVICE_DRIVER, "8021q",
+ NM_DEVICE_TYPE_DESC, "VLAN",
+ NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN,
+ NULL);
}
static const char *
@@ -758,8 +709,7 @@ get_virtual_iface_name (NMDeviceFactory *factory,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (VLAN, Vlan, vlan,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VLAN)
NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VLAN_SETTING_NAME),
- factory_iface->new_link = new_link;
- factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
+ factory_iface->create_device = create_device;
factory_iface->get_connection_parent = get_connection_parent;
factory_iface->get_virtual_iface_name = get_virtual_iface_name;
)
diff --git a/src/devices/nm-device-vlan.h b/src/devices/nm-device-vlan.h
index 4a27226fb7..e31e171d04 100644
--- a/src/devices/nm-device-vlan.h
+++ b/src/devices/nm-device-vlan.h
@@ -42,9 +42,6 @@ typedef enum {
#define NM_DEVICE_VLAN_PARENT "parent"
#define NM_DEVICE_VLAN_ID "vlan-id"
-/* Internal non-exported properties */
-#define NM_DEVICE_VLAN_INT_PARENT_DEVICE "int-parent-device"
-
typedef NMDevice NMDeviceVlan;
typedef NMDeviceClass NMDeviceVlanClass;
diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c
index 072d019a62..4f46f6aa8d 100644
--- a/src/devices/nm-device-vxlan.c
+++ b/src/devices/nm-device-vxlan.c
@@ -131,19 +131,22 @@ link_changed (NMDevice *device, NMPlatformLink *info)
update_properties (device);
}
-/**************************************************************/
-
static void
-nm_device_vxlan_init (NMDeviceVxlan *self)
+setup (NMDevice *device, NMPlatformLink *plink)
{
+ g_assert (plink->type == NM_LINK_TYPE_VXLAN);
+
+ NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->setup (device, plink);
+
+ update_properties (device);
}
+
+/**************************************************************/
+
static void
-constructed (GObject *object)
+nm_device_vxlan_init (NMDeviceVxlan *self)
{
- update_properties (NM_DEVICE (object));
-
- G_OBJECT_CLASS (nm_device_vxlan_parent_class)->constructed (object);
}
static void
@@ -223,10 +226,10 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
g_type_class_add_private (klass, sizeof (NMDeviceVxlanPrivate));
- object_class->constructed = constructed;
object_class->get_property = get_property;
device_class->link_changed = link_changed;
+ device_class->setup = setup;
/* properties */
g_object_class_install_property
@@ -351,10 +354,14 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass)
#define NM_VXLAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VXLAN_FACTORY, NMVxlanFactory))
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VXLAN,
- NM_DEVICE_PLATFORM_DEVICE, plink,
+ NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "Vxlan",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC,
NULL);
@@ -362,6 +369,6 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore,
NM_DEVICE_FACTORY_DEFINE_INTERNAL (VXLAN, Vxlan, vxlan,
NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VXLAN),
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
)
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 271201444f..2f21d6f409 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -96,7 +96,6 @@ static guint signals[LAST_SIGNAL] = { 0 };
enum {
PROP_0,
- PROP_PLATFORM_DEVICE,
PROP_UDI,
PROP_IFACE,
PROP_IP_IFACE,
@@ -380,6 +379,9 @@ static void _set_state_full (NMDevice *self,
static void nm_device_update_hw_address (NMDevice *self);
+static gboolean queued_ip4_config_change (gpointer user_data);
+static gboolean queued_ip6_config_change (gpointer user_data);
+
/***********************************************************/
#define QUEUED_PREFIX "queued state change to "
@@ -1548,6 +1550,95 @@ link_changed (NMDevice *self, NMPlatformLink *info)
nm_device_set_carrier (self, info->connected);
}
+/**
+ * nm_device_realize():
+ * @self: the #NMDevice
+ * @plink: an existing platform link or %NULL
+ * @error: location to store error, or %NULL
+ *
+ * Initializes and sets up the device using existing backing resources.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ */
+gboolean
+nm_device_realize (NMDevice *self, NMPlatformLink *plink, GError **error)
+{
+ /* Try to realize the device from existing resources */
+ if (NM_DEVICE_GET_CLASS (self)->realize) {
+ if (!NM_DEVICE_GET_CLASS (self)->realize (self, plink, error))
+ return FALSE;
+ }
+
+ NM_DEVICE_GET_CLASS (self)->setup (self, plink);
+
+ return TRUE;
+}
+
+/**
+ * nm_device_create_and_realize():
+ * @self: the #NMDevice
+ * @connection: the #NMConnection being activated
+ * @parent: the parent #NMDevice if any
+ * @error: location to store error, or %NULL
+ *
+ * Creates any backing resources needed to realize the device to proceed
+ * with activating @connection.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ */
+gboolean
+nm_device_create_and_realize (NMDevice *self,
+ NMConnection *connection,
+ NMDevice *parent,
+ GError **error)
+{
+ NMPlatformLink plink = { .type = NM_LINK_TYPE_UNKNOWN };
+
+ /* 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);
+
+ g_return_val_if_fail (nm_device_check_connection_compatible (self, connection), TRUE);
+ return TRUE;
+}
+
+static void
+update_device_from_platform_link (NMDevice *self, NMPlatformLink *plink)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ const char *udi;
+
+ g_return_if_fail (plink != NULL);
+
+ udi = nm_platform_link_get_udi (NM_PLATFORM_GET, plink->ifindex);
+ if (udi && !g_strcmp0 (udi, priv->udi)) {
+ g_free (priv->udi);
+ priv->udi = g_strdup (udi);
+ g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
+ }
+
+ if (!g_strcmp0 (plink->name, priv->iface)) {
+ g_free (priv->iface);
+ priv->iface = g_strdup (plink->name);
+ g_object_notify (G_OBJECT (self), NM_DEVICE_IFACE);
+ }
+
+ priv->ifindex = plink->ifindex;
+ g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX);
+
+ priv->up = NM_FLAGS_HAS (plink->flags, IFF_UP);
+ if (plink->driver && g_strcmp0 (plink->driver, priv->driver) != 0) {
+ g_free (priv->driver);
+ priv->driver = g_strdup (plink->driver);
+ g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER);
+ }
+ priv->platform_link_initialized = plink->initialized;
+}
+
static void
config_changed_update_ignore_carrier (NMConfig *config,
NMConfigData *config_data,
@@ -1571,6 +1662,120 @@ check_carrier (NMDevice *self)
nm_device_set_carrier (self, nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex));
}
+static void
+setup (NMDevice *self, NMPlatformLink *plink)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
+ static guint32 id = 0;
+
+ /* The device should not be realized */
+ g_return_if_fail (priv->ip_ifindex <= 0);
+ g_return_if_fail (priv->ip_iface == NULL);
+
+ g_object_freeze_notify (G_OBJECT (self));
+
+ if (plink) {
+ g_return_if_fail (priv->iface == NULL || strcmp (plink->name, priv->iface) == 0);
+ update_device_from_platform_link (self, plink);
+ }
+
+ if (priv->ifindex > 0) {
+ _LOGD (LOGD_DEVICE, "setup(): %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);
+
+ priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex);
+
+ if (nm_platform_link_is_software (NM_PLATFORM_GET, priv->ifindex))
+ priv->capabilities |= NM_DEVICE_CAP_IS_SOFTWARE;
+
+ priv->mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex);
+ g_object_notify (G_OBJECT (self), NM_DEVICE_MTU);
+
+ nm_platform_link_get_driver_info (NM_PLATFORM_GET,
+ priv->ifindex,
+ NULL,
+ &priv->driver_version,
+ &priv->firmware_version);
+ if (priv->driver_version)
+ g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION);
+ if (priv->firmware_version)
+ g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION);
+
+ if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET))
+ priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, priv->ifindex);
+ }
+
+ if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities)
+ priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self);
+
+ if (!priv->udi) {
+ /* Use a placeholder UDI until we get a real one */
+ priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++);
+ g_object_notify (G_OBJECT (self), NM_DEVICE_UDI);
+ }
+
+ /* trigger initial ip config change to initialize ip-config */
+ priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
+ priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
+
+ nm_device_update_hw_address (self);
+
+ if (priv->hw_addr_len) {
+ priv->initial_hw_addr = g_strdup (priv->hw_addr);
+ _LOGD (LOGD_DEVICE | LOGD_HW, "read initial MAC address %s", priv->initial_hw_addr);
+
+ if (priv->ifindex > 0) {
+ guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
+ size_t len = 0;
+
+ if (nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len)) {
+ g_warn_if_fail (len == priv->hw_addr_len);
+ priv->perm_hw_addr = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
+ _LOGD (LOGD_DEVICE | LOGD_HW, "read permanent MAC address %s",
+ priv->perm_hw_addr);
+ } else {
+ /* Fall back to current address */
+ _LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address");
+ priv->perm_hw_addr = g_strdup (priv->hw_addr);
+ }
+ }
+ }
+
+ /* Note: initial hardware address must be read before calling get_ignore_carrier() */
+ if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
+ NMConfig *config = nm_config_get ();
+
+ priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self);
+ g_signal_connect (G_OBJECT (config),
+ NM_CONFIG_SIGNAL_CONFIG_CHANGED,
+ G_CALLBACK (config_changed_update_ignore_carrier),
+ self);
+
+ check_carrier (self);
+ _LOGD (LOGD_HW,
+ "carrier is %s%s",
+ priv->carrier ? "ON" : "OFF",
+ priv->ignore_carrier ? " (but ignored)" : "");
+ } else {
+ /* Fake online link when carrier detection is not available. */
+ priv->carrier = TRUE;
+ }
+
+ 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);
+ }
+
+ g_object_thaw_notify (G_OBJECT (self));
+}
+
/**
* nm_device_notify_component_added():
* @self: the #NMDevice
@@ -8857,54 +9062,12 @@ nm_device_init (NMDevice *self)
priv->v6_commit_first_time = TRUE;
}
-static GObject*
-constructor (GType type,
- guint n_construct_params,
- GObjectConstructParam *construct_params)
+static void
+constructed (GObject *object)
{
- GObject *object;
- NMDevice *self;
- NMDevicePrivate *priv;
+ NMDevice *self = NM_DEVICE (object);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMPlatform *platform;
- static guint32 id = 0;
-
- object = G_OBJECT_CLASS (nm_device_parent_class)->constructor (type,
- n_construct_params,
- construct_params);
- if (!object)
- return NULL;
-
- self = NM_DEVICE (object);
- priv = NM_DEVICE_GET_PRIVATE (self);
-
- _LOGD (LOGD_DEVICE, "constructor(): %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), priv->ifindex);
-
- if (!priv->iface) {
- _LOGE (LOGD_DEVICE, "No device interface provided, ignoring");
- goto error;
- }
-
- if (!priv->udi) {
- /* Use a placeholder UDI until we get a real one */
- priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++);
- }
-
- if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities)
- priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self);
-
- if (priv->ifindex > 0) {
- priv->physical_port_id = nm_platform_link_get_physical_port_id (NM_PLATFORM_GET, priv->ifindex);
- priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex);
- if (nm_platform_link_is_software (NM_PLATFORM_GET, priv->ifindex))
- priv->capabilities |= NM_DEVICE_CAP_IS_SOFTWARE;
- priv->mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex);
-
- nm_platform_link_get_driver_info (NM_PLATFORM_GET,
- priv->ifindex,
- NULL,
- &priv->driver_version,
- &priv->firmware_version);
- }
if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities)
priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self);
@@ -8917,79 +9080,6 @@ constructor (GType type,
g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self);
g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self);
- /* trigger initial ip config change to initialize ip-config */
- priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self);
- priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
-
- if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) {
- int ip_ifindex = nm_device_get_ip_ifindex (self);
-
- if (ip_ifindex > 0)
- priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, ip_ifindex);
- }
-
- return object;
-
-error:
- g_object_unref (self);
- return NULL;
-}
-
-static void
-constructed (GObject *object)
-{
- NMDevice *self = NM_DEVICE (object);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- int master;
-
- nm_device_update_hw_address (self);
-
- if (priv->hw_addr_len) {
- priv->initial_hw_addr = g_strdup (priv->hw_addr);
- _LOGD (LOGD_DEVICE | LOGD_HW, "read initial MAC address %s", priv->initial_hw_addr);
-
- if (priv->ifindex > 0) {
- guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
- size_t len = 0;
-
- if (nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len)) {
- g_warn_if_fail (len == priv->hw_addr_len);
- priv->perm_hw_addr = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
- _LOGD (LOGD_DEVICE | LOGD_HW, "read permanent MAC address %s",
- priv->perm_hw_addr);
- } else {
- /* Fall back to current address */
- _LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address");
- priv->perm_hw_addr = g_strdup (priv->hw_addr);
- }
- }
- }
-
- /* Note: initial hardware address must be read before calling get_ignore_carrier() */
- if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
- NMConfig *config = nm_config_get ();
-
- priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self);
- g_signal_connect (G_OBJECT (config),
- NM_CONFIG_SIGNAL_CONFIG_CHANGED,
- G_CALLBACK (config_changed_update_ignore_carrier),
- self);
-
- check_carrier (self);
- _LOGD (LOGD_HW,
- "carrier is %s%s",
- priv->carrier ? "ON" : "OFF",
- priv->ignore_carrier ? " (but ignored)" : "");
- } else {
- /* Fake online link when carrier detection is not available. */
- priv->carrier = TRUE;
- }
-
- /* Enslave ourselves */
- master = nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex);
- if (master)
- device_set_master (self, master);
-
priv->con_provider = nm_connection_provider_get ();
g_assert (priv->con_provider);
g_signal_connect (priv->con_provider,
@@ -9117,25 +9207,10 @@ set_property (GObject *object, guint prop_id,
{
NMDevice *self = NM_DEVICE (object);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
- NMPlatformLink *platform_device;
const char *hw_addr, *p;
guint count;
switch (prop_id) {
- case PROP_PLATFORM_DEVICE:
- platform_device = g_value_get_pointer (value);
- if (platform_device) {
- g_free (priv->udi);
- priv->udi = g_strdup (nm_platform_link_get_udi (NM_PLATFORM_GET, platform_device->ifindex));
- g_free (priv->iface);
- priv->iface = g_strdup (platform_device->name);
- priv->ifindex = platform_device->ifindex;
- priv->up = NM_FLAGS_HAS (platform_device->flags, IFF_UP);
- g_free (priv->driver);
- priv->driver = g_strdup (platform_device->driver);
- priv->platform_link_initialized = platform_device->initialized;
- }
- break;
case PROP_UDI:
if (g_value_get_string (value)) {
g_free (priv->udi);
@@ -9365,7 +9440,6 @@ nm_device_class_init (NMDeviceClass *klass)
object_class->finalize = finalize;
object_class->set_property = set_property;
object_class->get_property = get_property;
- object_class->constructor = constructor;
object_class->constructed = constructed;
klass->link_changed = link_changed;
@@ -9385,6 +9459,7 @@ 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->is_up = is_up;
klass->bring_up = bring_up;
klass->take_down = take_down;
@@ -9393,12 +9468,6 @@ nm_device_class_init (NMDeviceClass *klass)
/* Properties */
g_object_class_install_property
- (object_class, PROP_PLATFORM_DEVICE,
- g_param_spec_pointer (NM_DEVICE_PLATFORM_DEVICE, "", "",
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property
(object_class, PROP_UDI,
g_param_spec_string (NM_DEVICE_UDI, "", "",
NULL,
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index c6d414bfdf..d849f6682f 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -129,6 +129,58 @@ typedef struct {
void (* link_changed) (NMDevice *self, NMPlatformLink *info);
+ /**
+ * realize():
+ * @self: the #NMDevice
+ * @plink: the #NMPlatformLink if backed by a kernel netdevice
+ * @error: location to store error, or %NULL
+ *
+ * Realize the device from existing backing resources. No resources
+ * should be created as a side-effect of this function. This function
+ * should only fail if critical device properties/resources (eg, VLAN ID)
+ * fail to be read or initialized, that would cause the device to be
+ * unusable. For example, for any properties required to realize the device
+ * during create_and_realize(), if reading those properties in realize()
+ * should fail, this function should probably return %FALSE and an error.
+ *
+ * Returns: %TRUE on success, %FALSE if some error ocurred when realizing
+ * the device from backing resources
+ */
+ gboolean (*realize) (NMDevice *self,
+ NMPlatformLink *plink,
+ GError **error);
+
+ /**
+ * create_and_realize():
+ * @self: the #NMDevice
+ * @connection: the #NMConnection being activated
+ * @parent: the parent #NMDevice, if any
+ * @out_plink: on success, a backing kernel network device if one exists
+ * @error: location to store error, or %NULL
+ *
+ * Create any backing resources (kernel devices, etc) required for this
+ * device to activate @connection. If the device is backed by a kernel
+ * network device, that device should be returned in @out_plink after
+ * being created.
+ *
+ * Returns: %TRUE on success, %FALSE on error
+ */
+ gboolean (*create_and_realize) (NMDevice *self,
+ NMConnection *connection,
+ NMDevice *parent,
+ NMPlatformLink *out_plink,
+ GError **error);
+
+ /**
+ * setup():
+ * @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).
+ */
+ void (*setup) (NMDevice *self, NMPlatformLink *plink);
+
/* Hardware state (IFF_UP) */
gboolean (*can_unmanaged_external_down) (NMDevice *self);
gboolean (*is_up) (NMDevice *self);
@@ -257,7 +309,6 @@ typedef struct {
NMConnection * (* new_default_connection) (NMDevice *self);
} NMDeviceClass;
-
typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device,
DBusGMethodInvocation *context,
GError *error,
@@ -392,6 +443,14 @@ void nm_device_set_nm_owned (NMDevice *device);
gboolean nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps);
+gboolean nm_device_realize (NMDevice *device,
+ NMPlatformLink *plink,
+ GError **error);
+gboolean nm_device_create_and_realize (NMDevice *self,
+ NMConnection *connection,
+ NMDevice *parent,
+ GError **error);
+
gboolean nm_device_get_autoconnect (NMDevice *device);
void nm_device_state_changed (NMDevice *device,
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index 38c125db45..145b854f69 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -669,38 +669,34 @@ release_slave (NMDevice *device,
return success;
}
-/******************************************************************/
-
-NMDevice *
-nm_device_team_new (NMPlatformLink *platform_device)
-{
- return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM,
- NM_DEVICE_PLATFORM_DEVICE, platform_device,
- NM_DEVICE_DRIVER, "team",
- NM_DEVICE_TYPE_DESC, "Team",
- NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TEAM,
- NM_DEVICE_IS_MASTER, TRUE,
- NULL);
-}
-
-NMDevice *
-nm_device_team_new_for_connection (NMConnection *connection, GError **error)
+static gboolean
+create_and_realize (NMDevice *device,
+ NMConnection *connection,
+ NMDevice *parent,
+ NMPlatformLink *out_plink,
+ GError **error)
{
- const char *iface = nm_connection_get_interface_name (connection);
+ const char *iface = nm_device_get_iface (device);
NMPlatformError plerr;
- g_assert (iface);
-
- plerr = nm_platform_team_add (NM_PLATFORM_GET, iface, NULL);
+ plerr = nm_platform_team_add (NM_PLATFORM_GET, iface, out_plink);
if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) {
g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED,
"Failed to create team master interface '%s' for '%s': %s",
iface,
nm_connection_get_id (connection),
nm_platform_error_to_string (plerr));
- return NULL;
+ return FALSE;
}
+ return TRUE;
+}
+
+/******************************************************************/
+
+NMDevice *
+nm_device_team_new (const char *iface)
+{
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM,
NM_DEVICE_IFACE, iface,
NM_DEVICE_DRIVER, "team",
@@ -798,6 +794,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
object_class->set_property = set_property;
object_class->dispose = dispose;
+ parent_class->create_and_realize = create_and_realize;
parent_class->get_generic_capabilities = get_generic_capabilities;
parent_class->is_available = is_available;
parent_class->check_connection_compatible = check_connection_compatible;
diff --git a/src/devices/team/nm-device-team.h b/src/devices/team/nm-device-team.h
index 76cdba1396..2436705712 100644
--- a/src/devices/team/nm-device-team.h
+++ b/src/devices/team/nm-device-team.h
@@ -34,20 +34,12 @@ G_BEGIN_DECLS
#define NM_DEVICE_TEAM_SLAVES "slaves"
-typedef struct {
- NMDevice parent;
-} NMDeviceTeam;
-
-typedef struct {
- NMDeviceClass parent;
-
-} NMDeviceTeamClass;
-
+typedef NMDevice NMDeviceTeam;
+typedef NMDeviceClass NMDeviceTeamClass;
GType nm_device_team_get_type (void);
-NMDevice *nm_device_team_new (NMPlatformLink *platform_device);
-NMDevice *nm_device_team_new_for_connection (NMConnection *connection, GError **error);
+NMDevice *nm_device_team_new (const char *iface);
G_END_DECLS
diff --git a/src/devices/team/nm-team-factory.c b/src/devices/team/nm-team-factory.c
index d87919b6b7..949e01d15d 100644
--- a/src/devices/team/nm-team-factory.c
+++ b/src/devices/team/nm-team-factory.c
@@ -48,18 +48,13 @@ nm_device_factory_create (GError **error)
/************************************************************************/
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
- return nm_device_team_new (plink);
-}
-
-static NMDevice *
-create_virtual_device_for_connection (NMDeviceFactory *factory,
- NMConnection *connection,
- NMDevice *parent,
- GError **error)
-{
- return nm_device_team_new_for_connection (connection, error);
+ return nm_device_team_new (iface);
}
NM_DEVICE_FACTORY_DECLARE_TYPES (
@@ -77,8 +72,7 @@ nm_team_factory_init (NMTeamFactory *self)
static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
- factory_iface->new_link = new_link;
- factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
+ factory_iface->create_device = create_device;
factory_iface->get_supported_types = get_supported_types;
}
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index ad401f5e52..f7fffd272e 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -419,12 +419,10 @@ state_changed (NMDevice *device,
/*******************************************************************/
NMDevice *
-nm_device_olpc_mesh_new (NMPlatformLink *platform_device)
+nm_device_olpc_mesh_new (const char *iface)
{
- g_return_val_if_fail (platform_device != NULL, NULL);
-
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_OLPC_MESH,
- NM_DEVICE_PLATFORM_DEVICE, platform_device,
+ NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "802.11 OLPC Mesh",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH,
NULL);
diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h
index 8d6895f27a..63895a88fd 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.h
+++ b/src/devices/wifi/nm-device-olpc-mesh.h
@@ -65,7 +65,7 @@ struct _NMDeviceOlpcMeshClass
GType nm_device_olpc_mesh_get_type (void);
-NMDevice *nm_device_olpc_mesh_new (NMPlatformLink *platform_device);
+NMDevice *nm_device_olpc_mesh_new (const char *iface);
G_END_DECLS
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index 0c434bf462..58da7cc065 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -445,6 +445,14 @@ periodic_update_cb (gpointer user_data)
return TRUE;
}
+static void
+setup (NMDevice *device, NMPlatformLink *plink)
+{
+ NM_DEVICE_CLASS (nm_device_wifi_parent_class)->setup (device, plink);
+
+ g_object_notify (G_OBJECT (device), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS);
+}
+
static gboolean
bring_up (NMDevice *device, gboolean *no_firmware)
{
@@ -2844,12 +2852,10 @@ set_enabled (NMDevice *device, gboolean enabled)
/********************************************************************/
NMDevice *
-nm_device_wifi_new (NMPlatformLink *platform_device)
+nm_device_wifi_new (const char *iface)
{
- g_return_val_if_fail (platform_device != NULL, NULL);
-
return (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIFI,
- NM_DEVICE_PLATFORM_DEVICE, platform_device,
+ NM_DEVICE_IFACE, iface,
NM_DEVICE_TYPE_DESC, "802.11 WiFi",
NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI,
NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN,
@@ -2958,6 +2964,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
object_class->dispose = dispose;
object_class->finalize = finalize;
+ parent_class->setup = setup;
parent_class->bring_up = bring_up;
parent_class->can_auto_connect = can_auto_connect;
parent_class->is_available = is_available;
diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h
index c74ff1c5bf..e2954b9c5c 100644
--- a/src/devices/wifi/nm-device-wifi.h
+++ b/src/devices/wifi/nm-device-wifi.h
@@ -73,7 +73,7 @@ struct _NMDeviceWifiClass
GType nm_device_wifi_get_type (void);
-NMDevice *nm_device_wifi_new (NMPlatformLink *platform_device);
+NMDevice * nm_device_wifi_new (const char *iface);
G_END_DECLS
diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c
index c4b4042e70..eca4e1de53 100644
--- a/src/devices/wifi/nm-wifi-factory.c
+++ b/src/devices/wifi/nm-wifi-factory.c
@@ -59,13 +59,19 @@ nm_device_factory_create (GError **error)
/**************************************************************************/
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
+ g_return_val_if_fail (plink != NULL, NULL);
+
if (plink->type == NM_LINK_TYPE_WIFI)
- return nm_device_wifi_new (plink);
+ return nm_device_wifi_new (iface);
else if (plink->type == NM_LINK_TYPE_OLPC_MESH)
- return nm_device_olpc_mesh_new (plink);
- g_assert_not_reached ();
+ return nm_device_olpc_mesh_new (iface);
+ g_return_val_if_reached (NULL);
}
NM_DEVICE_FACTORY_DECLARE_TYPES (
@@ -76,7 +82,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES (
static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
factory_iface->get_supported_types = get_supported_types;
}
diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c
index 49b0b0af53..863c5828fe 100644
--- a/src/devices/wwan/nm-wwan-factory.c
+++ b/src/devices/wwan/nm-wwan-factory.c
@@ -96,9 +96,14 @@ NM_DEVICE_FACTORY_DECLARE_TYPES (
)
static NMDevice *
-new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error)
+create_device (NMDeviceFactory *factory,
+ const char *iface,
+ NMPlatformLink *plink,
+ NMConnection *connection,
+ gboolean *out_ignore)
{
- g_warn_if_fail (plink->type == NM_LINK_TYPE_WWAN_ETHERNET);
+ g_return_val_if_fail (plink, NULL);
+ g_return_val_if_fail (plink->type == NM_LINK_TYPE_WWAN_ETHERNET, NULL);
*out_ignore = TRUE;
return NULL;
}
@@ -126,7 +131,7 @@ static void
device_factory_interface_init (NMDeviceFactory *factory_iface)
{
factory_iface->get_supported_types = get_supported_types;
- factory_iface->new_link = new_link;
+ factory_iface->create_device = create_device;
factory_iface->start = start;
}
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 7d1d2b3ca5..c2188b9ce0 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -1032,11 +1032,13 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
nm_owned = !nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface);
- device = nm_device_factory_create_virtual_device_for_connection (factory,
- connection,
- parent,
- error);
+ device = nm_device_factory_create_device (factory, iface, NULL, connection, NULL, error);
if (device) {
+ if (!nm_device_create_and_realize (device, connection, parent, error)) {
+ g_clear_object (&device);
+ goto out;
+ }
+
if (nm_owned)
nm_device_set_nm_owned (device);
@@ -1045,6 +1047,9 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError
*/
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);
}
@@ -1837,7 +1842,15 @@ factory_device_added_cb (NMDeviceFactory *factory,
NMDevice *device,
gpointer user_data)
{
- add_device (NM_MANAGER (user_data), device, TRUE);
+ GError *error = NULL;
+
+ if (nm_device_realize (device, NULL, &error))
+ add_device (NM_MANAGER (user_data), device, TRUE);
+ else {
+ nm_log_warn (LOGD_DEVICE, "(%s): failed to realize device: %s",
+ nm_device_get_iface (device), error->message);
+ g_error_free (error);
+ }
}
static gboolean
@@ -1885,7 +1898,7 @@ platform_link_added (NMManager *self,
if (factory) {
gboolean ignore = FALSE;
- device = nm_device_factory_new_link (factory, plink, &ignore, &error);
+ device = nm_device_factory_create_device (factory, plink->name, plink, NULL, &ignore, &error);
if (!device) {
if (!ignore) {
nm_log_warn (LOGD_HW, "%s: factory failed to create device: %s",
@@ -1893,6 +1906,11 @@ platform_link_added (NMManager *self,
g_clear_error (&error);
}
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;
}
}