Creates virtual devices as needed when the manager is initialized or as needed if connections are added on the fly.
Signed-off-by: Thomas Graf <[email protected]> --- src/nm-manager.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++--- src/nm-system.c | 31 ++++++++++++++++ src/nm-system.h | 3 ++ 3 files changed, 130 insertions(+), 5 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 9200f34..b930f17 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -925,12 +925,97 @@ get_active_connections (NMManager *manager, NMConnection *filter) /* Settings stuff via NMSettings */ /*******************************************************************/ +static gboolean +connection_needs_virtual_device (NMConnection *connection) +{ + NMSettingConnection *connection_setting; + const char *type; + + connection_setting = (NMSettingConnection *) + nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + g_assert(connection_setting); + + type = nm_setting_connection_get_connection_type (connection_setting); + g_assert (type); + + if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) + return TRUE; + + return FALSE; +} + +static gboolean +system_update_virtual_device (NMConnection *connection) +{ + NMSettingConnection *connection_setting; + NMSetting *type_setting; + const char *type; + + connection_setting = (NMSettingConnection *) + nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + g_assert(connection_setting); + + type = nm_setting_connection_get_connection_type (connection_setting); + g_assert (type); + + type_setting = nm_connection_get_setting_by_name (connection, type); + + if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME)) + return nm_system_add_bonding_master (NM_SETTING_BOND (type_setting)); + + return TRUE; +} + static void -connections_changed (NMSettings *settings, +system_create_virtual_devices (NMSettings *settings) +{ + GSList *iter, *connections; + + nm_log_info (LOGD_CORE, "Creating virtual devices"); + + connections = nm_settings_get_connections (settings); + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = NM_CONNECTION (iter->data); + + if (connection_needs_virtual_device (connection)) + system_update_virtual_device (connection); + } + + g_slist_free (connections); +} + +static void +connection_added (NMSettings *settings, NMSettingsConnection *connection, NMManager *manager) { bluez_manager_resync_devices (manager); + + if (connection_needs_virtual_device (NM_CONNECTION (connection))) + system_update_virtual_device (NM_CONNECTION (connection)); +} + +static void +connection_changed (NMSettings *settings, + NMSettingsConnection *connection, + NMManager *manager) +{ + bluez_manager_resync_devices (manager); + + /* FIXME: Some virtual devices may need to be updated in the future. */ +} + +static void +connection_removed (NMSettings *settings, + NMSettingsConnection *connection, + NMManager *manager) +{ + bluez_manager_resync_devices (manager); + + /* + * Do not delete existing virtual devices to keep connectivity up. + * Virtual devices are reused when NetworkManager is restarted. + */ } static void @@ -2823,6 +2908,12 @@ nm_manager_start (NMManager *self) nm_udev_manager_query_devices (priv->udev_mgr); bluez_manager_resync_devices (self); + + /* + * Connections added before the manager is started do not emit + * connection-added signals thus devices have to be created manually. + */ + system_create_virtual_devices (priv->settings); } static gboolean @@ -3095,13 +3186,13 @@ nm_manager_get (NMSettings *settings, g_signal_connect (priv->settings, "notify::" NM_SETTINGS_HOSTNAME, G_CALLBACK (system_hostname_changed_cb), singleton); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, - G_CALLBACK (connections_changed), singleton); + G_CALLBACK (connection_added), singleton); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, - G_CALLBACK (connections_changed), singleton); + G_CALLBACK (connection_changed), singleton); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, - G_CALLBACK (connections_changed), singleton); + G_CALLBACK (connection_removed), singleton); g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, - G_CALLBACK (connections_changed), singleton); + G_CALLBACK (connection_changed), singleton); dbus_g_connection_register_g_object (bus, NM_DBUS_PATH, G_OBJECT (singleton)); diff --git a/src/nm-system.c b/src/nm-system.c index 473fcec..2d0393a 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -1175,3 +1175,34 @@ nm_system_device_set_priority (int ifindex, rtnl_route_put (found); } } + +/** + * nm_system_add_bonding_master: + * @setting: bonding setting + * + * Adds a virtual bonding device if it does not exist yet. + * + * Returns: %TRUE on success, %FALSE on failure + */ +gboolean +nm_system_add_bonding_master(NMSettingBond *setting) +{ + struct nl_sock *sock; + const char *name; + int err; + + sock = nm_netlink_get_default_handle (); + name = nm_setting_bond_get_device_name (setting); + g_assert (name); + + /* Existing bonding devices with matching name will be reused */ + err = rtnl_link_bond_add (sock, name, NULL); + if (err < 0) { + nm_log_err (LOGD_DEVICE, "(%s): error %d returned from " + "rtnl_link_bond_add(): %s", + name, err, nl_geterror (err)); + return FALSE; + } + + return TRUE; +} diff --git a/src/nm-system.h b/src/nm-system.h index ae4e7d9..a606503 100644 --- a/src/nm-system.h +++ b/src/nm-system.h @@ -30,6 +30,7 @@ #include <glib.h> #include "nm-device.h" #include "nm-ip4-config.h" +#include "nm-setting-bond.h" /* Prototypes for system/distribution dependent functions, * implemented in the backend files in backends/ directory @@ -89,4 +90,6 @@ gboolean nm_system_iface_set_mtu (int ifindex, guint32 mtu); gboolean nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac); +gboolean nm_system_add_bonding_master (NMSettingBond *setting); + #endif -- 1.7.6 _______________________________________________ networkmanager-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/networkmanager-list
