summary refs log tree commit diff
path: root/src/devices/nm-device-bond.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/nm-device-bond.c')
-rw-r--r--src/devices/nm-device-bond.c227
1 files changed, 99 insertions, 128 deletions
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 6f8caeb4..9d9fe426 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -23,30 +23,30 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 
-#include <netinet/ether.h>
 #include <errno.h>
 #include <stdlib.h>
 
 #include "gsystem-local-alloc.h"
 #include "nm-device-bond.h"
 #include "nm-logging.h"
-#include "nm-utils.h"
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
 #include "nm-platform.h"
 #include "nm-dbus-glib-types.h"
 #include "nm-dbus-manager.h"
 #include "nm-enum-types.h"
+#include "nm-device-factory.h"
+#include "nm-core-internal.h"
 
 #include "nm-device-bond-glue.h"
 
+#include "nm-device-logging.h"
+_LOG_DECLARE_SELF(NMDeviceBond);
 
 G_DEFINE_TYPE (NMDeviceBond, nm_device_bond, NM_TYPE_DEVICE)
 
 #define NM_DEVICE_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_BOND, NMDeviceBondPrivate))
 
-#define NM_BOND_ERROR (nm_bond_error_quark ())
-
 typedef struct {
 	int dummy;
 } NMDeviceBondPrivate;
@@ -60,17 +60,6 @@ enum {
 
 /******************************************************************/
 
-static GQuark
-nm_bond_error_quark (void)
-{
-	static GQuark quark = 0;
-	if (!quark)
-		quark = g_quark_from_static_string ("nm-bond-error");
-	return quark;
-}
-
-/******************************************************************/
-
 static guint32
 get_generic_capabilities (NMDevice *dev)
 {
@@ -110,7 +99,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection)
 		return FALSE;
 
 	/* Bond connections must specify the virtual interface name */
-	iface = nm_connection_get_virtual_iface_name (connection);
+	iface = nm_connection_get_interface_name (connection);
 	if (!iface || strcmp (nm_device_get_iface (device), iface))
 		return FALSE;
 
@@ -126,17 +115,14 @@ complete_connection (NMDevice *device,
                      const GSList *existing_connections,
                      GError **error)
 {
-	NMSettingBond *s_bond, *tmp;
-	guint32 i = 0;
-	char *name;
-	const GSList *iter;
-	gboolean found;
+	NMSettingBond *s_bond;
 
 	nm_utils_complete_generic (connection,
 	                           NM_SETTING_BOND_SETTING_NAME,
 	                           existing_connections,
-	                           _("Bond connection %d"),
 	                           NULL,
+	                           _("Bond connection"),
+	                           "bond",
 	                           TRUE);
 
 	s_bond = nm_connection_get_setting_bond (connection);
@@ -145,34 +131,6 @@ complete_connection (NMDevice *device,
 		nm_connection_add_setting (connection, NM_SETTING (s_bond));
 	}
 
-	/* Grab the first name that doesn't exist in either our connections
-	 * or a device on the system.
-	 */
-	while (i < 500 && !nm_setting_bond_get_interface_name (s_bond)) {
-		name = g_strdup_printf ("bond%u", i);
-		/* check interface names */
-		if (!nm_platform_link_exists (name)) {
-			/* check existing bond connections */
-			for (iter = existing_connections, found = FALSE; iter; iter = g_slist_next (iter)) {
-				NMConnection *candidate = iter->data;
-
-				tmp = nm_connection_get_setting_bond (candidate);
-				if (tmp && nm_connection_is_type (candidate, NM_SETTING_BOND_SETTING_NAME)) {
-					if (g_strcmp0 (nm_setting_bond_get_interface_name (tmp), name) == 0) {
-						found = TRUE;
-						break;
-					}
-				}
-			}
-
-			if (!found)
-				g_object_set (G_OBJECT (s_bond), NM_SETTING_BOND_INTERFACE_NAME, name, NULL);
-		}
-
-		g_free (name);
-		i++;
-	}
-
 	return TRUE;
 }
 
@@ -181,14 +139,13 @@ complete_connection (NMDevice *device,
 static gboolean
 set_bond_attr (NMDevice *device, const char *attr, const char *value)
 {
+	NMDeviceBond *self = NM_DEVICE_BOND (device);
 	gboolean ret;
 	int ifindex = nm_device_get_ifindex (device);
 
 	ret = nm_platform_master_set_option (ifindex, attr, value);
-	if (!ret) {
-		nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute "
-		             "'%s' to '%s'", nm_device_get_ip_iface (device), attr, value);
-	}
+	if (!ret)
+		_LOGW (LOGD_HW, "failed to set bonding attribute '%s' to '%s'", attr, value);
 	return ret;
 }
 
@@ -209,14 +166,12 @@ static void
 update_connection (NMDevice *device, NMConnection *connection)
 {
 	NMSettingBond *s_bond = nm_connection_get_setting_bond (connection);
-	const char *ifname = nm_device_get_iface (device);
 	int ifindex = nm_device_get_ifindex (device);
 	const char **options;
 
 	if (!s_bond) {
 		s_bond = (NMSettingBond *) nm_setting_bond_new ();
 		nm_connection_add_setting (connection, (NMSetting *) s_bond);
-		g_object_set (s_bond, NM_SETTING_BOND_INTERFACE_NAME, ifname, NULL);
 	}
 
 	/* Read bond options from sysfs and update the Bond setting to match */
@@ -243,6 +198,19 @@ update_connection (NMDevice *device, NMConnection *connection)
 	}
 }
 
+static gboolean
+master_update_slave_connection (NMDevice *self,
+                                NMDevice *slave,
+                                NMConnection *connection,
+                                GError **error)
+{
+	g_object_set (nm_connection_get_setting_connection (connection),
+	              NM_SETTING_CONNECTION_MASTER, nm_device_get_iface (self),
+	              NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BOND_SETTING_NAME,
+	              NULL);
+	return TRUE;
+}
+
 static void
 set_arp_targets (NMDevice *device,
                  const char *value,
@@ -380,6 +348,10 @@ apply_bonding_config (NMDevice *device)
 	set_simple_option (device, "xmit_hash_policy", s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY);
 	set_simple_option (device, "resend_igmp", s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP);
 
+	if (   g_strcmp0 (mode, "4") == 0
+	    || g_strcmp0 (mode, "802.3ad") == 0)
+		set_simple_option (device, "lacp_rate", s_bond, NM_SETTING_BOND_OPTION_LACP_RATE);
+
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 }
 
@@ -410,8 +382,8 @@ enslave_slave (NMDevice *device,
                NMConnection *connection,
                gboolean configure)
 {
+	NMDeviceBond *self = NM_DEVICE_BOND (device);
 	gboolean success = TRUE, no_firmware = FALSE;
-	const char *iface = nm_device_get_ip_iface (device);
 	const char *slave_iface = nm_device_get_ip_iface (slave);
 
 	nm_device_master_check_slave_physical_port (device, slave, LOGD_BOND);
@@ -425,9 +397,9 @@ enslave_slave (NMDevice *device,
 		if (!success)
 			return FALSE;
 
-		nm_log_info (LOGD_BOND, "(%s): enslaved bond slave %s", iface, slave_iface);
+		_LOGI (LOGD_BOND, "enslaved bond slave %s", slave_iface);
 	} else
-		nm_log_info (LOGD_BOND, "(%s): bond slave %s was enslaved", iface, slave_iface);
+		_LOGI (LOGD_BOND, "bond slave %s was enslaved", slave_iface);
 
 	g_object_notify (G_OBJECT (device), NM_DEVICE_BOND_SLAVES);
 	return TRUE;
@@ -438,6 +410,7 @@ release_slave (NMDevice *device,
                NMDevice *slave,
                gboolean configure)
 {
+	NMDeviceBond *self = NM_DEVICE_BOND (device);
 	gboolean success = TRUE, no_firmware = FALSE;
 
 	if (configure) {
@@ -445,17 +418,14 @@ release_slave (NMDevice *device,
 		                                    nm_device_get_ip_ifindex (slave));
 
 		if (success) {
-			nm_log_info (LOGD_BOND, "(%s): released bond slave %s",
-			             nm_device_get_ip_iface (device),
-			             nm_device_get_ip_iface (slave));
+			_LOGI (LOGD_BOND, "released bond slave %s",
+			       nm_device_get_ip_iface (slave));
 		} else {
-			nm_log_warn (LOGD_BOND, "(%s): failed to release bond slave %s",
-			             nm_device_get_ip_iface (device),
-			             nm_device_get_ip_iface (slave));
+			_LOGW (LOGD_BOND, "failed to release bond slave %s",
+			       nm_device_get_ip_iface (slave));
 		}
 	} else {
-		nm_log_info (LOGD_BOND, "(%s): bond slave %s was released",
-		             nm_device_get_ip_iface (device),
+		_LOGI (LOGD_BOND, "bond slave %s was released",
 		             nm_device_get_ip_iface (slave));
 	}
 
@@ -467,10 +437,8 @@ release_slave (NMDevice *device,
 		 * IFF_UP), so we must bring it back up here to ensure carrier changes and
 		 * other state is noticed by the now-released slave.
 		 */
-		if (!nm_device_bring_up (slave, TRUE, &no_firmware)) {
-			nm_log_warn (LOGD_BOND, "(%s): released bond slave could not be brought up.",
-			             nm_device_get_iface (slave));
-		}
+		if (!nm_device_bring_up (slave, TRUE, &no_firmware))
+			_LOGW (LOGD_BOND, "released bond slave could not be brought up.");
 	}
 
 	return success;
@@ -478,57 +446,6 @@ release_slave (NMDevice *device,
 
 /******************************************************************/
 
-NMDevice *
-nm_device_bond_new (NMPlatformLink *platform_device)
-{
-	g_return_val_if_fail (platform_device != NULL, NULL);
-
-	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
-	                                  NM_DEVICE_PLATFORM_DEVICE, platform_device,
-	                                  NM_DEVICE_DRIVER, "bonding",
-	                                  NM_DEVICE_TYPE_DESC, "Bond",
-	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
-	                                  NM_DEVICE_IS_MASTER, TRUE,
-	                                  NULL);
-}
-
-NMDevice *
-nm_device_bond_new_for_connection (NMConnection *connection)
-{
-	const char *iface;
-
-	g_return_val_if_fail (connection != NULL, NULL);
-
-	iface = nm_connection_get_virtual_iface_name (connection);
-	g_return_val_if_fail (iface != NULL, NULL);
-
-	if (   !nm_platform_bond_add (iface)
-	    && nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) {
-		nm_log_warn (LOGD_DEVICE | LOGD_BOND, "(%s): failed to create bonding master interface for '%s': %s",
-		             iface, nm_connection_get_id (connection),
-		             nm_platform_get_error_msg ());
-		return NULL;
-	}
-
-	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
-	                                  NM_DEVICE_IFACE, iface,
-	                                  NM_DEVICE_DRIVER, "bonding",
-	                                  NM_DEVICE_TYPE_DESC, "Bond",
-	                                  NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
-	                                  NM_DEVICE_IS_MASTER, TRUE,
-	                                  NULL);
-}
-
-static void
-constructed (GObject *object)
-{
-	G_OBJECT_CLASS (nm_device_bond_parent_class)->constructed (object);
-
-	nm_log_dbg (LOGD_HW | LOGD_BOND, "(%s): kernel ifindex %d",
-	            nm_device_get_iface (NM_DEVICE (object)),
-	            nm_device_get_ifindex (NM_DEVICE (object)));
-}
-
 static void
 nm_device_bond_init (NMDeviceBond * self)
 {
@@ -579,7 +496,6 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
 	parent_class->connection_type = NM_SETTING_BOND_SETTING_NAME;
 
 	/* virtual methods */
-	object_class->constructed = constructed;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
 
@@ -590,6 +506,7 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
 	parent_class->complete_connection = complete_connection;
 
 	parent_class->update_connection = update_connection;
+	parent_class->master_update_slave_connection = master_update_slave_connection;
 
 	parent_class->act_stage1_prepare = act_stage1_prepare;
 	parent_class->enslave_slave = enslave_slave;
@@ -598,15 +515,69 @@ nm_device_bond_class_init (NMDeviceBondClass *klass)
 	/* properties */
 	g_object_class_install_property
 		(object_class, PROP_SLAVES,
-		 g_param_spec_boxed (NM_DEVICE_BOND_SLAVES,
-		                     "Slaves",
-		                     "Slaves",
+		 g_param_spec_boxed (NM_DEVICE_BOND_SLAVES, "", "",
 		                     DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
-		                     G_PARAM_READABLE));
+		                     G_PARAM_READABLE |
+		                     G_PARAM_STATIC_STRINGS));
 
 	nm_dbus_manager_register_exported_type (nm_dbus_manager_get (),
 	                                        G_TYPE_FROM_CLASS (klass),
 	                                        &dbus_glib_nm_device_bond_object_info);
+}
+
+/*************************************************************/
+
+#define NM_TYPE_BOND_FACTORY (nm_bond_factory_get_type ())
+#define NM_BOND_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BOND_FACTORY, NMBondFactory))
+
+static NMDevice *
+new_link (NMDeviceFactory *factory, NMPlatformLink *plink, GError **error)
+{
+	if (plink->type == NM_LINK_TYPE_BOND) {
+		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);
+	}
+	return NULL;
+}
+
+static NMDevice *
+create_virtual_device_for_connection (NMDeviceFactory *factory,
+                                      NMConnection *connection,
+                                      NMDevice *parent,
+                                      GError **error)
+{
+	const char *iface;
+
+	if (!nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME))
+		return NULL;
+
+	iface = nm_connection_get_interface_name (connection);
+	g_return_val_if_fail (iface != NULL, NULL);
 
-	dbus_g_error_domain_register (NM_BOND_ERROR, NULL, NM_TYPE_BOND_ERROR);
+	if (   !nm_platform_bond_add (iface)
+		&& nm_platform_get_error () != NM_PLATFORM_ERROR_EXISTS) {
+		nm_log_warn (LOGD_DEVICE | LOGD_BOND, "(%s): failed to create bonding master interface for '%s': %s",
+			         iface, nm_connection_get_id (connection),
+			         nm_platform_get_error_msg ());
+		return NULL;
+	}
+
+	return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND,
+		                              NM_DEVICE_IFACE, iface,
+		                              NM_DEVICE_DRIVER, "bonding",
+		                              NM_DEVICE_TYPE_DESC, "Bond",
+		                              NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND,
+		                              NM_DEVICE_IS_MASTER, TRUE,
+		                              NULL);
 }
+
+DEFINE_DEVICE_FACTORY_INTERNAL(BOND, Bond, bond,
+	factory_iface->new_link = new_link;
+	factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection;
+	)
+