[PATCH 2/9] bonding: bonding master device creation



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 <tgraf redhat com>
---
 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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]