[PATCH 3/8] bonding: kernel bonding device creation



Creates virtual kernel devices as needed. Since the manager is
initialized after the connections have been loaded no
CONNECTIONS_ADDED notification is received for connections parsed
at startup.

Therefore walks the loaded connections looking for bonding
connections.

Connections added on the fly are handled via the notifications.

Connection renaming and deleting is not supported yet.

Signed-off-by: Thomas Graf <tgraf redhat com>
---
 src/nm-manager.c |   84 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 src/nm-system.c  |   31 ++++++++++++++++++++
 src/nm-system.h  |    3 ++
 3 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/src/nm-manager.c b/src/nm-manager.c
index b09cceb..fbeb8a9 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -924,12 +924,80 @@ get_active_connections (NMManager *manager, NMConnection *filter)
 /* Settings stuff via NMSettings                                   */
 /*******************************************************************/
 
+static gboolean
+connection_needs_virtual_device (NMConnection *connection)
+{
+	if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean
+system_update_virtual_device (NMConnection *connection)
+{
+	if (nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)) {
+		NMSettingBond *s_bond;
+
+		s_bond = nm_connection_get_setting_bond (connection);
+		g_assert (s_bond);
+
+		return nm_system_add_bonding_master (s_bond);
+	}
+
+	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 +2891,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
@@ -3099,13 +3173,13 @@ nm_manager_new (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..27344ed 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_interface_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.4



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