diff options
author | Dan Williams <dcbw@redhat.com> | 2014-09-18 17:50:47 -0500 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2015-05-06 16:14:25 -0500 |
commit | 179d56c73c35e83368589b40a8a2d429b41a4dbf (patch) | |
tree | aebae80b63107a65ce163a7c4e02df3267d93468 | |
parent | 42b272b604d8a40d699e1e08beb6135ad1f0caba (diff) | |
download | NetworkManager-179d56c73c35e83368589b40a8a2d429b41a4dbf.tar.gz |
core: move virtual interface name handling into device plugins
Instead of having a bunch of logic in the Manager for determining the
VLAN and Infiniband virtual interface names, move the type-specific
logic into the plugins themselves.
-rw-r--r-- | src/devices/nm-device-factory.c | 95 | ||||
-rw-r--r-- | src/devices/nm-device-factory.h | 35 | ||||
-rw-r--r-- | src/devices/nm-device-infiniband.c | 32 | ||||
-rw-r--r-- | src/devices/nm-device-vlan.c | 53 | ||||
-rw-r--r-- | src/nm-manager.c | 266 |
5 files changed, 282 insertions, 199 deletions
diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index 1038f75191..0357845c12 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -160,61 +160,92 @@ nm_device_factory_create_virtual_device_for_connection (NMDeviceFactory *factory return interface->create_virtual_device_for_connection (factory, connection, parent, error); } +const char * +nm_device_factory_get_connection_parent (NMDeviceFactory *factory, + NMConnection *connection) +{ + g_return_val_if_fail (factory != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); + + if (!nm_connection_is_virtual (connection)) + return NULL; + + if (NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_connection_parent) + return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_connection_parent (factory, connection); + return NULL; +} + +static char * +get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + const char *iface; + + /* For any other virtual connection, NMSettingConnection:interface-name is + * the virtual device name. + */ + iface = nm_connection_get_interface_name (connection); + g_return_val_if_fail (iface != NULL, NULL); + return g_strdup (iface); +} + +char * +nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + g_return_val_if_fail (factory != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); + + if (!nm_connection_is_virtual (connection)) + return NULL; + + if (NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_virtual_iface_name) + return NM_DEVICE_FACTORY_GET_INTERFACE (factory)->get_virtual_iface_name (factory, connection, parent_iface); + return NULL; +} + /*******************************************************************/ static void -interface_init (gpointer g_iface) +default_init (NMDeviceFactory *factory_iface) { - GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); - static gboolean initialized = FALSE; - - if (G_LIKELY (initialized)) - return; + factory_iface->get_virtual_iface_name = get_virtual_iface_name; /* Signals */ signals[DEVICE_ADDED] = g_signal_new (NM_DEVICE_FACTORY_DEVICE_ADDED, - iface_type, + NM_TYPE_DEVICE_FACTORY, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMDeviceFactory, device_added), NULL, NULL, NULL, G_TYPE_NONE, 1, NM_TYPE_DEVICE); signals[COMPONENT_ADDED] = g_signal_new (NM_DEVICE_FACTORY_COMPONENT_ADDED, - iface_type, + NM_TYPE_DEVICE_FACTORY, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMDeviceFactory, component_added), g_signal_accumulator_true_handled, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_OBJECT); - - initialized = TRUE; } GType nm_device_factory_get_type (void) { - static GType device_factory_type = 0; - - if (!device_factory_type) { - const GTypeInfo device_factory_info = { - sizeof (NMDeviceFactory), /* class_size */ - interface_init, /* base_init */ - NULL, /* base_finalize */ - NULL, - NULL, /* class_finalize */ - NULL, /* class_data */ - 0, - 0, /* n_preallocs */ - NULL - }; - - device_factory_type = g_type_register_static (G_TYPE_INTERFACE, - "NMDeviceFactory", - &device_factory_info, - 0); - g_type_interface_add_prerequisite (device_factory_type, G_TYPE_OBJECT); + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + GType g_define_type_id = + g_type_register_static_simple (G_TYPE_INTERFACE, + g_intern_static_string ("NMDeviceFactory"), + sizeof (NMDeviceFactory), + (GClassInitFunc) default_init, + 0, + (GInstanceInitFunc) NULL, + (GTypeFlags) 0); + g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); } - - return device_factory_type; + return g_define_type_id__volatile; } /*******************************************************************/ diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h index c6e4fa6914..40050d4dd3 100644 --- a/src/devices/nm-device-factory.h +++ b/src/devices/nm-device-factory.h @@ -128,6 +128,34 @@ struct _NMDeviceFactory { NMDevice *parent, GError **error); + /** + * get_connection_parent: + * @factory: the #NMDeviceFactory + * @connection: the #NMConnection to return the parent name for, if supported + * + * Given a connection, returns the a parent interface name, parent connection + * UUID, or parent device hardware address for @connection. + * + * Returns: the parent interface name, parent connection UUID, parent + * device hardware address, or %NULL + */ + const char * (*get_connection_parent) (NMDeviceFactory *factory, + NMConnection *connection); + + /** + * get_virtual_iface_name: + * @factory: the #NMDeviceFactory + * @connection: the #NMConnection to return the virtual interface name for + * @parent_iface: parent interface name + * + * Given a connection, returns the interface name that a device activating + * that connection would have. + * + * Returns: the interface name, or %NULL + */ + char * (*get_virtual_iface_name) (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface); /* Signals */ @@ -162,6 +190,13 @@ void nm_device_factory_get_supported_types (NMDeviceFactory *factory, const NMLinkType **out_link_types, const char ***out_setting_types); +const char *nm_device_factory_get_connection_parent (NMDeviceFactory *factory, + NMConnection *connection); + +char * nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface); + void nm_device_factory_start (NMDeviceFactory *factory); NMDevice * nm_device_factory_new_link (NMDeviceFactory *factory, diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index 9f2119abac..c7b8787c45 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -345,10 +345,42 @@ create_virtual_device_for_connection (NMDeviceFactory *factory, NULL); } +static const char * +get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) +{ + NMSettingInfiniband *s_infiniband; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME), NULL); + + s_infiniband = nm_connection_get_setting_infiniband (connection); + g_assert (s_infiniband); + + return nm_setting_infiniband_get_parent (s_infiniband); +} + +static char * +get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + NMSettingInfiniband *s_infiniband; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME), NULL); + + s_infiniband = nm_connection_get_setting_infiniband (connection); + g_assert (s_infiniband); + + g_return_val_if_fail (g_strcmp0 (parent_iface, nm_setting_infiniband_get_parent (s_infiniband)) == 0, NULL); + + return g_strdup (nm_setting_infiniband_get_virtual_interface_name (s_infiniband)); +} + 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->get_connection_parent = get_connection_parent; + factory_iface->get_virtual_iface_name = get_virtual_iface_name; ) diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 55292173af..ba79a6ccb1 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -743,10 +743,63 @@ create_virtual_device_for_connection (NMDeviceFactory *factory, return device; } +static const char * +get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) +{ + NMSettingVlan *s_vlan; + NMSettingWired *s_wired; + const char *parent = NULL; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME), NULL); + + s_vlan = nm_connection_get_setting_vlan (connection); + g_assert (s_vlan); + + parent = nm_setting_vlan_get_parent (s_vlan); + if (parent) + return parent; + + /* Try the hardware address from the VLAN connection's hardware setting */ + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) + return nm_setting_wired_get_mac_address (s_wired); + + return NULL; +} + +static char * +get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + const char *ifname; + NMSettingVlan *s_vlan; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME), NULL); + + s_vlan = nm_connection_get_setting_vlan (connection); + g_assert (s_vlan); + + if (!parent_iface) + return NULL; + + ifname = nm_connection_get_interface_name (connection); + if (ifname) + return g_strdup (ifname); + + /* If the connection doesn't specify the interface name for the VLAN + * device, we create one for it using the VLAN ID and the parent + * interface's name. + */ + return nm_utils_new_vlan_name (parent_iface, nm_setting_vlan_get_id (s_vlan)); +} + 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->get_connection_parent = get_connection_parent; + factory_iface->get_virtual_iface_name = get_virtual_iface_name; ) diff --git a/src/nm-manager.c b/src/nm-manager.c index edfd3513c2..6bb867ca71 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -514,23 +514,19 @@ nm_manager_get_device_by_ifindex (NMManager *manager, int ifindex) } static NMDevice * -get_device_from_hwaddr (NMManager *self, const char *setting_mac) +find_device_by_hw_addr (NMManager *manager, const char *hwaddr) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - const char *device_mac; GSList *iter; + const char *device_addr; - if (!setting_mac) - return NULL; - - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *device = iter->data; + g_return_val_if_fail (hwaddr != NULL, NULL); - device_mac = nm_device_get_hw_address (iter->data); - if (!device_mac) - continue; - if (nm_utils_hwaddr_matches (setting_mac, -1, device_mac, -1)) - return device; + if (nm_utils_hwaddr_valid (hwaddr, -1)) { + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + device_addr = nm_device_get_hw_address (NM_DEVICE (iter->data)); + if (device_addr && nm_utils_hwaddr_matches (hwaddr, -1, device_addr, -1)) + return NM_DEVICE (iter->data); + } } return NULL; } @@ -538,14 +534,13 @@ get_device_from_hwaddr (NMManager *self, const char *setting_mac) static NMDevice * find_device_by_ip_iface (NMManager *self, const gchar *iface) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GSList *iter; - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *candidate = iter->data; + g_return_val_if_fail (iface != NULL, NULL); - if (g_strcmp0 (nm_device_get_ip_iface (candidate), iface) == 0) - return candidate; + for (iter = NM_MANAGER_GET_PRIVATE (self)->devices; iter; iter = g_slist_next (iter)) { + if (g_strcmp0 (nm_device_get_ip_iface (NM_DEVICE (iter->data)), iface) == 0) + return NM_DEVICE (iter->data); } return NULL; } @@ -873,87 +868,56 @@ nm_manager_get_state (NMManager *manager) return NM_MANAGER_GET_PRIVATE (manager)->state; } -/*******************************************************************/ -/* Settings stuff via NMSettings */ -/*******************************************************************/ +/***************************/ static NMDevice * -find_vlan_parent (NMManager *self, - NMConnection *connection) +find_parent_device_for_connection (NMManager *self, NMConnection *connection) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMSettingVlan *s_vlan; - NMSettingWired *s_wired; + NMDeviceFactory *factory; + const char *parent_name = NULL; NMConnection *parent_connection; - const char *parent_iface; - NMDevice *parent = NULL; - const char *setting_mac; + NMDevice *parent, *first_compatible = NULL; GSList *iter; - /* The 'parent' property could be given by an interface name, a - * connection UUID, or the MAC address of an NMSettingWired. - */ - s_vlan = nm_connection_get_setting_vlan (connection); - g_return_val_if_fail (s_vlan != NULL, NULL); - - s_wired = nm_connection_get_setting_wired (connection); - setting_mac = s_wired ? nm_setting_wired_get_mac_address (s_wired) : NULL; - - parent_iface = nm_setting_vlan_get_parent (s_vlan); - if (parent_iface) { - parent = find_device_by_ip_iface (self, parent_iface); - if (parent) - return parent; - - if (nm_utils_is_uuid (parent_iface)) { - /* Try as a connection UUID */ - parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (priv->settings, parent_iface); - if (parent_connection) { - /* Check if the parent connection is activated on some device already */ - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMActRequest *req; - NMConnection *candidate; - - req = nm_device_get_act_request (NM_DEVICE (iter->data)); - if (req) { - candidate = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (req)); - if (candidate == parent_connection) - return NM_DEVICE (iter->data); - } - } + factory = nm_device_factory_manager_find_factory_for_connection (connection); + if (!factory) + return NULL; - /* Check the hardware address of the parent connection */ - return get_device_from_hwaddr (self, setting_mac); - } - return NULL; - } - } + parent_name = nm_device_factory_get_connection_parent (factory, connection); + if (!parent_name) + return NULL; - /* Try the hardware address from the VLAN connection's hardware setting */ - return get_device_from_hwaddr (self, setting_mac); -} + /* Try as an interface name */ + parent = find_device_by_ip_iface (self, parent_name); + if (parent) + return parent; -static NMDevice * -find_infiniband_parent (NMManager *self, - NMConnection *connection) -{ - NMSettingInfiniband *s_infiniband; - const char *parent_iface; - NMDevice *parent = NULL; - const char *setting_mac; + /* Maybe a hardware address */ + parent = find_device_by_hw_addr (self, parent_name); + if (parent) + return parent; + + /* Maybe a connection UUID */ + parent_connection = (NMConnection *) nm_settings_get_connection_by_uuid (priv->settings, parent_name); + if (!parent_connection) + return NULL; + + /* Check if the parent connection is currently activated or is comaptible + * with some known device. + */ + for (iter = priv->devices; iter; iter = iter->next) { + NMDevice *candidate = iter->data; - s_infiniband = nm_connection_get_setting_infiniband (connection); - g_return_val_if_fail (s_infiniband != NULL, NULL); + if (nm_device_get_connection (candidate) == parent_connection) + return candidate; - parent_iface = nm_setting_infiniband_get_parent (s_infiniband); - if (parent_iface) { - parent = find_device_by_ip_iface (self, parent_iface); - if (parent) - return parent; + if ( !first_compatible + && nm_device_check_connection_compatible (candidate, parent_connection)) + first_compatible = candidate; } - setting_mac = nm_setting_infiniband_get_mac_address (s_infiniband); - return get_device_from_hwaddr (self, setting_mac); + return first_compatible; } /** @@ -961,86 +925,69 @@ find_infiniband_parent (NMManager *self, * @self: the #NMManager * @connection: the #NMConnection representing a virtual interface * @out_parent: on success, the parent device if any + * @error: an error if determining the virtual interface name failed * * Given @connection, returns the interface name that the connection - * would represent. If the interface name is not given by the connection, - * this may require constructing it based on information in the connection - * and existing network interfaces. + * would represent if it is a virtual connection. %NULL is returned and + * @error is set if the connection is not virtual, or if the name could + * not be determined. * * Returns: the expected interface name (caller takes ownership), or %NULL */ static char * get_virtual_iface_name (NMManager *self, NMConnection *connection, - NMDevice **out_parent) + NMDevice **out_parent, + GError **error) { + NMDeviceFactory *factory; + char *iface = NULL; NMDevice *parent = NULL; - const char *ifname; if (out_parent) *out_parent = NULL; - if (!nm_connection_is_virtual (connection)) + if (!nm_connection_is_virtual (connection)) { + g_set_error (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "NetworkManager plugin for '%s' unavailable", + nm_connection_get_connection_type (connection)); return NULL; - - ifname = nm_connection_get_interface_name (connection); - - if (nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)) { - NMSettingVlan *s_vlan; - char *vname; - - s_vlan = nm_connection_get_setting_vlan (connection); - g_return_val_if_fail (s_vlan != NULL, NULL); - - parent = find_vlan_parent (self, connection); - if (!parent) - return NULL; - - if (!nm_device_supports_vlans (parent)) { - nm_log_warn (LOGD_DEVICE, "(%s): No support for VLANs on interface %s of type %s", - ifname ? ifname : nm_connection_get_id (connection), - nm_device_get_ip_iface (parent), - nm_device_get_type_desc (parent)); - return NULL; - } - - /* If the connection doesn't specify the interface name for the VLAN - * device, we create one for it using the VLAN ID and the parent - * interface's name. - */ - if (ifname) - vname = g_strdup (ifname); - else { - vname = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent), - nm_setting_vlan_get_id (s_vlan)); - } - if (out_parent) - *out_parent = parent; - return vname; } - if (nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)) { - NMSettingInfiniband *s_infiniband; - - parent = find_infiniband_parent (self, connection); - if (!parent) - return NULL; + factory = nm_device_factory_manager_find_factory_for_connection (connection); + if (!factory) { + nm_log_warn (LOGD_DEVICE, "(%s) NetworkManager plugin for '%s' unavailable", + nm_connection_get_id (connection), + nm_connection_get_connection_type (connection)); + g_set_error (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "NetworkManager plugin for '%s' unavailable", + nm_connection_get_connection_type (connection)); + return NULL; + } - s_infiniband = nm_connection_get_setting_infiniband (connection); - if (out_parent) - *out_parent = parent; - return g_strdup (nm_setting_infiniband_get_virtual_interface_name (s_infiniband)); + parent = find_parent_device_for_connection (self, connection); + iface = nm_device_factory_get_virtual_iface_name (factory, + connection, + parent ? nm_device_get_ip_iface (parent) : NULL); + if (!iface) { + nm_log_warn (LOGD_DEVICE, "(%s) failed to determine virtual interface name", + nm_connection_get_id (connection)); + g_set_error_literal (error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "failed to determine virtual interface name"); + return NULL; } - /* For any other virtual connection, NMSettingConnection:interface-name is - * the virtual device name. - */ - g_return_val_if_fail (ifname != NULL, NULL); - return g_strdup (ifname); + if (out_parent) + *out_parent = parent; + return iface; } -/***************************/ - /** * system_create_virtual_device: * @self: the #NMManager @@ -1066,16 +1013,9 @@ system_create_virtual_device (NMManager *self, NMConnection *connection, GError g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); - iface = get_virtual_iface_name (self, connection, &parent); - if (!iface) { - nm_log_dbg (LOGD_DEVICE, "(%s) failed to determine virtual interface name", - nm_connection_get_id (connection)); - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_FAILED, - "failed to determine virtual interface name"); + iface = get_virtual_iface_name (self, connection, &parent, error); + if (!iface) return NULL; - } /* Make sure we didn't create a device for this connection already */ for (iter = priv->devices; iter; iter = g_slist_next (iter)) { @@ -2251,13 +2191,10 @@ find_master (NMManager *self, NMConnection *candidate = iter->data; char *vname; - if (nm_connection_is_virtual (candidate)) { - vname = get_virtual_iface_name (self, candidate, NULL); - if ( g_strcmp0 (master, vname) == 0 - && is_compatible_with_slave (candidate, connection)) - master_connection = candidate; - g_free (vname); - } + vname = get_virtual_iface_name (self, connection, NULL, NULL); + if (g_strcmp0 (master, vname) == 0 && is_compatible_with_slave (candidate, connection)) + master_connection = candidate; + g_free (vname); } g_slist_free (connections); } @@ -2939,17 +2876,12 @@ validate_activation_request (NMManager *self, } if (is_software) { - /* Look for an existing device with the connection's interface name */ char *iface; - iface = get_virtual_iface_name (self, connection, NULL); - if (!iface) { - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_DEVICE, - "Failed to determine connection's virtual interface name"); + /* Look for an existing device with the connection's interface name */ + iface = get_virtual_iface_name (self, connection, NULL, error); + if (!iface) goto error; - } device = find_device_by_ip_iface (self, iface); g_free (iface); |