diff options
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; } } |