summary refs log tree commit diff
path: root/libnm-core/nm-setting-bond.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2016-04-06 00:46:19 +0200
committerMichael Biebl <biebl@debian.org>2016-04-06 00:46:19 +0200
commit2bfb3eb7d0323e69affca154395f51d8b577414d (patch)
treee3130a5146441296df6d08a0f4ac7222a854c8f8 /libnm-core/nm-setting-bond.c
parentd9c99a29a0d3384c9c3d2adce430f5cb1134ab6a (diff)
Imported Upstream version 1.1.93 upstream/1.1.93
Diffstat (limited to 'libnm-core/nm-setting-bond.c')
-rw-r--r--libnm-core/nm-setting-bond.c197
1 files changed, 153 insertions, 44 deletions
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c
index 4d40de00..e008878d 100644
--- a/libnm-core/nm-setting-bond.c
+++ b/libnm-core/nm-setting-bond.c
@@ -32,6 +32,7 @@
 #include "nm-utils-private.h"
 #include "nm-connection-private.h"
 #include "nm-setting-infiniband.h"
+#include "nm-core-internal.h"
 
 /**
  * SECTION:nm-setting-bond
@@ -57,14 +58,6 @@ enum {
 	LAST_PROP
 };
 
-enum {
-	TYPE_INT,
-	TYPE_STR,
-	TYPE_BOTH,
-	TYPE_IP,
-	TYPE_IFNAME,
-};
-
 typedef struct {
 	const char *opt;
 	const char *val;
@@ -75,28 +68,40 @@ typedef struct {
 } BondDefault;
 
 static const BondDefault defaults[] = {
-	{ NM_SETTING_BOND_OPTION_MODE,             "balance-rr", TYPE_BOTH, 0, 6,
+	{ NM_SETTING_BOND_OPTION_MODE,             "balance-rr", NM_BOND_OPTION_TYPE_BOTH, 0, 6,
 	  { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", NULL } },
-	{ NM_SETTING_BOND_OPTION_MIIMON,           "100",        TYPE_INT, 0, G_MAXINT },
-	{ NM_SETTING_BOND_OPTION_DOWNDELAY,        "0",          TYPE_INT, 0, G_MAXINT },
-	{ NM_SETTING_BOND_OPTION_UPDELAY,          "0",          TYPE_INT, 0, G_MAXINT },
-	{ NM_SETTING_BOND_OPTION_ARP_INTERVAL,     "0",          TYPE_INT, 0, G_MAXINT },
-	{ NM_SETTING_BOND_OPTION_ARP_IP_TARGET,    "",           TYPE_IP },
-	{ NM_SETTING_BOND_OPTION_ARP_VALIDATE,     "0",          TYPE_BOTH, 0, 3,
+	{ NM_SETTING_BOND_OPTION_MIIMON,           "100",        NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_DOWNDELAY,        "0",          NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_UPDELAY,          "0",          NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_ARP_INTERVAL,     "0",          NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_ARP_IP_TARGET,    "",           NM_BOND_OPTION_TYPE_IP },
+	{ NM_SETTING_BOND_OPTION_ARP_VALIDATE,     "none",       NM_BOND_OPTION_TYPE_BOTH, 0, 3,
 	  { "none", "active", "backup", "all", NULL } },
-	{ NM_SETTING_BOND_OPTION_PRIMARY,          "",           TYPE_IFNAME },
-	{ NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, "0",          TYPE_BOTH, 0, 2,
+	{ NM_SETTING_BOND_OPTION_PRIMARY,          "",           NM_BOND_OPTION_TYPE_IFNAME },
+	{ NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, "always",     NM_BOND_OPTION_TYPE_BOTH, 0, 2,
 	  { "always", "better", "failure", NULL } },
-	{ NM_SETTING_BOND_OPTION_FAIL_OVER_MAC,    "0",          TYPE_BOTH, 0, 2,
+	{ NM_SETTING_BOND_OPTION_FAIL_OVER_MAC,    "none",       NM_BOND_OPTION_TYPE_BOTH, 0, 2,
 	  { "none", "active", "follow", NULL } },
-	{ NM_SETTING_BOND_OPTION_USE_CARRIER,      "1",          TYPE_INT, 0, 1 },
-	{ NM_SETTING_BOND_OPTION_AD_SELECT,        "0",          TYPE_BOTH, 0, 2,
+	{ NM_SETTING_BOND_OPTION_USE_CARRIER,      "1",          NM_BOND_OPTION_TYPE_INT, 0, 1 },
+	{ NM_SETTING_BOND_OPTION_AD_SELECT,        "stable",     NM_BOND_OPTION_TYPE_BOTH, 0, 2,
 	  { "stable", "bandwidth", "count", NULL } },
-	{ NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, "0",          TYPE_BOTH, 0, 2,
+	{ NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, "layer2",     NM_BOND_OPTION_TYPE_BOTH, 0, 2,
 	  { "layer2", "layer3+4", "layer2+3", NULL } },
-	{ NM_SETTING_BOND_OPTION_RESEND_IGMP,      "1",          TYPE_INT, 0, 255 },
-	{ NM_SETTING_BOND_OPTION_LACP_RATE,        "0",          TYPE_BOTH, 0, 1,
+	{ NM_SETTING_BOND_OPTION_RESEND_IGMP,      "1",          NM_BOND_OPTION_TYPE_INT, 0, 255 },
+	{ NM_SETTING_BOND_OPTION_LACP_RATE,        "slow",       NM_BOND_OPTION_TYPE_BOTH, 0, 1,
 	  { "slow", "fast", NULL } },
+	{ NM_SETTING_BOND_OPTION_ACTIVE_SLAVE,     "",           NM_BOND_OPTION_TYPE_IFNAME },
+	{ NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO,"65535",      NM_BOND_OPTION_TYPE_INT, 1, 65535 },
+	{ NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM,  "",           NM_BOND_OPTION_TYPE_MAC },
+	{ NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY, "0",          NM_BOND_OPTION_TYPE_INT, 0, 1023},
+	{ NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE,"0",          NM_BOND_OPTION_TYPE_INT, 0, 1},
+	{ NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS,  "any",        NM_BOND_OPTION_TYPE_BOTH, 0, 1, {"any", "all"}},
+	{ NM_SETTING_BOND_OPTION_MIN_LINKS,        "0",          NM_BOND_OPTION_TYPE_INT, 0, G_MAXINT },
+	{ NM_SETTING_BOND_OPTION_NUM_GRAT_ARP,     "1",          NM_BOND_OPTION_TYPE_INT, 0, 255 },
+	{ NM_SETTING_BOND_OPTION_NUM_UNSOL_NA,     "1",          NM_BOND_OPTION_TYPE_INT, 0, 255 },
+	{ NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE,"1",          NM_BOND_OPTION_TYPE_INT, 0, 65535 },
+	{ NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB,   "1",          NM_BOND_OPTION_TYPE_INT, 0, 1 },
+	{ NM_SETTING_BOND_OPTION_LP_INTERVAL,      "1",          NM_BOND_OPTION_TYPE_INT, 1, G_MAXINT },
 };
 
 /**
@@ -268,16 +273,18 @@ nm_setting_bond_validate_option (const char *name,
 			if (value == NULL)
 				return TRUE;
 			switch (defaults[i].opt_type) {
-			case TYPE_INT:
+			case NM_BOND_OPTION_TYPE_INT:
 				return validate_int (name, value, &defaults[i]);
-			case TYPE_STR:
+			case NM_BOND_OPTION_TYPE_STRING:
 				return validate_list (name, value, &defaults[i]);
-			case TYPE_BOTH:
+			case NM_BOND_OPTION_TYPE_BOTH:
 				return (   validate_int (name, value, &defaults[i])
 				        || validate_list (name, value, &defaults[i]));
-			case TYPE_IP:
+			case NM_BOND_OPTION_TYPE_IP:
 				return validate_ip (name, value);
-			case TYPE_IFNAME:
+			case NM_BOND_OPTION_TYPE_MAC:
+				return nm_utils_hwaddr_valid (value, ETH_ALEN);
+			case NM_BOND_OPTION_TYPE_IFNAME:
 				return validate_ifname (name, value);
 			}
 			return FALSE;
@@ -433,6 +440,29 @@ nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name)
 	g_assert_not_reached ();
 }
 
+/**
+ * nm_setting_bond_get_option_type:
+ * @setting: the #NMSettingBond
+ * @name: the name of the option
+ *
+ * Returns: the type of the bond option.
+ **/
+NMBondOptionType
+_nm_setting_bond_get_option_type (NMSettingBond *setting, const char *name)
+{
+	guint i;
+
+	g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NM_BOND_OPTION_TYPE_INT);
+	g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NM_BOND_OPTION_TYPE_INT);
+
+	for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
+		if (nm_streq0 (defaults[i].opt, name))
+			return defaults[i].opt_type;
+	}
+	/* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */
+	g_assert_not_reached ();
+}
+
 static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
@@ -440,6 +470,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	GHashTableIter iter;
 	const char *key, *value;
 	int mode, miimon = 0, arp_interval = 0;
+	int num_grat_arp = -1, num_unsol_na = -1;
 	const char *mode_orig, *mode_new;
 	const char *arp_ip_target = NULL;
 	const char *lacp_rate;
@@ -464,6 +495,12 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
 	if (value)
 		arp_interval = atoi (value);
+	value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP);
+	if (value)
+		num_grat_arp = atoi (value);
+	value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA);
+	if (value)
+		num_unsol_na = atoi (value);
 
 	/* Can only set one of miimon and arp_interval */
 	if (miimon > 0 && arp_interval > 0) {
@@ -474,11 +511,12 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		             NM_SETTING_BOND_OPTION_MIIMON,
 		             NM_SETTING_BOND_OPTION_ARP_INTERVAL);
 		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+		return FALSE;
 	}
 
 	/* Verify bond mode */
-	mode_orig = value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE);
-	if (!value) {
+	mode_orig = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE);
+	if (!mode_orig) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -487,7 +525,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 		return FALSE;
 	}
-	mode = nm_utils_bond_mode_string_to_int (value);
+	mode = nm_utils_bond_mode_string_to_int (mode_orig);
 	if (mode == -1) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
@@ -497,24 +535,24 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 		return FALSE;
 	}
-	mode_new = value = nm_utils_bond_mode_int_to_string (mode);
+	mode_new = nm_utils_bond_mode_int_to_string (mode);
 
 	/* Make sure mode is compatible with other settings */
-	if (   strcmp (value, "balance-alb") == 0
-	    || strcmp (value, "balance-tlb") == 0) {
+	if (   strcmp (mode_new, "balance-alb") == 0
+	    || strcmp (mode_new, "balance-tlb") == 0) {
 		if (arp_interval > 0) {
 			g_set_error (error,
 			             NM_CONNECTION_ERROR,
 			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
 			             _("'%s=%s' is incompatible with '%s > 0'"),
-			             NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+			             NM_SETTING_BOND_OPTION_MODE, mode_new, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
 			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
 	}
 
 	primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY);
-	if (strcmp (value, "active-backup") == 0) {
+	if (strcmp (mode_new, "active-backup") == 0) {
 		if (primary && !nm_utils_iface_valid_name (primary)) {
 			g_set_error (error,
 			             NM_CONNECTION_ERROR,
@@ -538,12 +576,12 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	}
 
 	if (nm_connection_get_setting_infiniband (connection)) {
-		if (strcmp (value, "active-backup") != 0) {
+		if (strcmp (mode_new, "active-backup") != 0) {
 			g_set_error (error,
 			             NM_CONNECTION_ERROR,
 			             NM_CONNECTION_ERROR_INVALID_PROPERTY,
 			             _("'%s=%s' is not a valid configuration for '%s'"),
-			             NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_INFINIBAND_SETTING_NAME);
+			             NM_SETTING_BOND_OPTION_MODE, mode_new, NM_SETTING_INFINIBAND_SETTING_NAME);
 			g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
 			return FALSE;
 		}
@@ -629,8 +667,9 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 
 	lacp_rate = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_LACP_RATE);
 	if (   lacp_rate
-	    && (g_strcmp0 (value, "802.3ad") != 0 && g_strcmp0 (value, "4") != 0)
-	    && (strcmp (lacp_rate, "slow") != 0 && strcmp (lacp_rate, "0") != 0)) {
+	    && g_strcmp0 (mode_new, "802.3ad")
+	    && strcmp (lacp_rate, "slow") != 0
+	    && strcmp (lacp_rate, "0") != 0) {
 		g_set_error (error,
 		             NM_CONNECTION_ERROR,
 		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -640,6 +679,18 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
+	if (   (num_grat_arp != -1 && num_unsol_na != -1)
+	    && (num_grat_arp != num_unsol_na)) {
+		g_set_error (error,
+		             NM_CONNECTION_ERROR,
+		             NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		             _("'%s' and '%s' cannot have different values"),
+		             NM_SETTING_BOND_OPTION_NUM_GRAT_ARP,
+		             NM_SETTING_BOND_OPTION_NUM_UNSOL_NA);
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+		return FALSE;
+	}
+
 	if (!_nm_connection_verify_required_interface_name (connection, error))
 		return FALSE;
 
@@ -658,6 +709,63 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	return TRUE;
 }
 
+static gboolean
+options_hash_match (NMSettingBond *s_bond, GHashTable *options1, GHashTable *options2)
+{
+	GHashTableIter iter;
+	const char *key, *value, *value2;
+
+	g_hash_table_iter_init (&iter, options1);
+	while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) {
+		value2 = g_hash_table_lookup (options2, key);
+
+		if (!value2) {
+			if (nm_streq (key, "num_grat_arp"))
+				value2 = g_hash_table_lookup (options2, "num_unsol_na");
+			else if (nm_streq (key, "num_unsol_na"))
+				value2 = g_hash_table_lookup (options2, "num_grat_arp");
+		}
+
+		if (value2) {
+			if (nm_streq (value, value2))
+				continue;
+		} else {
+			if (nm_streq (value, nm_setting_bond_get_option_default (s_bond, key)))
+				continue;
+		}
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+options_equal (NMSettingBond *s_bond, GHashTable *options1, GHashTable *options2)
+{
+	return    options_hash_match (s_bond, options1, options2)
+	       && options_hash_match (s_bond, options2, options1);
+}
+
+static gboolean
+compare_property (NMSetting *setting,
+                  NMSetting *other,
+                  const GParamSpec *prop_spec,
+                  NMSettingCompareFlags flags)
+{
+	NMSettingClass *parent_class;
+
+	if (nm_streq0 (prop_spec->name, NM_SETTING_BOND_OPTIONS)) {
+		return options_equal (NM_SETTING_BOND (setting),
+		                      NM_SETTING_BOND_GET_PRIVATE (setting)->options,
+		                      NM_SETTING_BOND_GET_PRIVATE (other)->options);
+	}
+
+	/* Otherwise chain up to parent to handle generic compare */
+	parent_class = NM_SETTING_CLASS (nm_setting_bond_parent_class);
+	return parent_class->compare_property (setting, other, prop_spec, flags);
+}
+
 static void
 nm_setting_bond_init (NMSettingBond *setting)
 {
@@ -721,10 +829,11 @@ nm_setting_bond_class_init (NMSettingBondClass *setting_class)
 	g_type_class_add_private (setting_class, sizeof (NMSettingBondPrivate));
 
 	/* virtual methods */
-	object_class->set_property = set_property;
-	object_class->get_property = get_property;
-	object_class->finalize     = finalize;
-	parent_class->verify       = verify;
+	object_class->set_property     = set_property;
+	object_class->get_property     = get_property;
+	object_class->finalize         = finalize;
+	parent_class->verify           = verify;
+	parent_class->compare_property = compare_property;
 
 	/* Properties */
 	/**