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.c154
1 files changed, 76 insertions, 78 deletions
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 9c98c8ea..3f17849b 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -15,7 +15,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright 2011 - 2012 Red Hat, Inc.
+ * Copyright 2011 - 2016 Red Hat, Inc.
  */
 
 #include "nm-default.h"
@@ -118,12 +118,15 @@ complete_connection (NMDevice *device,
 /******************************************************************/
 
 static gboolean
-set_bond_attr (NMDevice *device, const char *attr, const char *value)
+set_bond_attr (NMDevice *device, NMBondMode mode, const char *attr, const char *value)
 {
 	NMDeviceBond *self = NM_DEVICE_BOND (device);
 	gboolean ret;
 	int ifindex = nm_device_get_ifindex (device);
 
+	if (!_nm_setting_bond_option_supported (attr, mode))
+		return FALSE;
+
 	ret = nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, attr, value);
 	if (!ret)
 		_LOGW (LOGD_HW, "failed to set bonding attribute '%s' to '%s'", attr, value);
@@ -134,10 +137,10 @@ set_bond_attr (NMDevice *device, const char *attr, const char *value)
 static gboolean
 ignore_if_zero (const char *option, const char *value)
 {
-	if (strcmp (option, "arp_interval") &&
-	    strcmp (option, "miimon") &&
-	    strcmp (option, "downdelay") &&
-	    strcmp (option, "updelay"))
+	if (!NM_IN_STRSET (option, NM_SETTING_BOND_OPTION_ARP_INTERVAL,
+	                           NM_SETTING_BOND_OPTION_DOWNDELAY,
+	                           NM_SETTING_BOND_OPTION_MIIMON,
+	                           NM_SETTING_BOND_OPTION_UPDELAY))
 		return FALSE;
 
 	return g_strcmp0 (value, "0") == 0 ? TRUE : FALSE;
@@ -173,7 +176,7 @@ update_connection (NMDevice *device, NMConnection *connection)
 		    && !ignore_if_zero (*options, value)
 		    && !nm_streq0 (value, defvalue)) {
 			/* Replace " " with "," for arp_ip_targets from the kernel */
-			if (strcmp (*options, "arp_ip_target") == 0) {
+			if (strcmp (*options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET) == 0) {
 				for (p = value; *p; p++) {
 					if (*p == ' ')
 						*p = ',';
@@ -201,6 +204,7 @@ master_update_slave_connection (NMDevice *self,
 
 static void
 set_arp_targets (NMDevice *device,
+                 NMBondMode mode,
                  const char *value,
                  const char *delim,
                  const char *prefix)
@@ -214,7 +218,7 @@ set_arp_targets (NMDevice *device,
 	for (iter = items; iter && *iter; iter++) {
 		if (*iter[0]) {
 			tmp = g_strdup_printf ("%s%s", prefix, *iter);
-			set_bond_attr (device, "arp_ip_target", tmp);
+			set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_IP_TARGET, tmp);
 			g_free (tmp);
 		}
 	}
@@ -223,7 +227,7 @@ set_arp_targets (NMDevice *device,
 
 static void
 set_simple_option (NMDevice *device,
-                   const char *attr,
+                   NMBondMode mode,
                    NMSettingBond *s_bond,
                    const char *opt)
 {
@@ -232,18 +236,20 @@ set_simple_option (NMDevice *device,
 	value = nm_setting_bond_get_option_by_name (s_bond, opt);
 	if (!value)
 		value = nm_setting_bond_get_option_default (s_bond, opt);
-	set_bond_attr (device, attr, value);
+	set_bond_attr (device, mode, opt, value);
 }
 
 static NMActStageReturn
 apply_bonding_config (NMDevice *device)
 {
+	NMDeviceBond *self = NM_DEVICE_BOND (device);
 	NMConnection *connection;
 	NMSettingBond *s_bond;
 	int ifindex = nm_device_get_ifindex (device);
-	const char *mode, *value;
+	const char *mode_str, *value;
 	char *contents;
 	gboolean set_arp_interval = TRUE;
+	NMBondMode mode;
 
 	/* Option restrictions:
 	 *
@@ -263,98 +269,90 @@ apply_bonding_config (NMDevice *device)
 	s_bond = nm_connection_get_setting_bond (connection);
 	g_assert (s_bond);
 
-	mode = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE);
-	if (mode == NULL)
-		mode = "balance-rr";
+	mode_str = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE);
+	if (!mode_str)
+		mode_str = "balance-rr";
+
+	mode = _nm_setting_bond_mode_from_string (mode_str);
+	if (mode == NM_BOND_MODE_UNKNOWN) {
+		_LOGW (LOGD_BOND, "unknown bond mode '%s'", mode_str);
+		return NM_ACT_STAGE_RETURN_FAILURE;
+	}
+
+	/* Set mode first, as some other options (e.g. arp_interval) are valid
+	 * only for certain modes.
+	 */
+
+	set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_MODE, mode_str);
 
 	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MIIMON);
 	if (value && atoi (value)) {
 		/* clear arp interval */
-		set_bond_attr (device, "arp_interval", "0");
+		set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0");
 		set_arp_interval = FALSE;
 
-		set_bond_attr (device, "miimon", value);
-		set_simple_option (device, "updelay", s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
-		set_simple_option (device, "downdelay", s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
+		set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_MIIMON, value);
+		set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
+		set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
 	} else if (!value) {
-		/* If not given, and arp_interval is not given, default to 100 */
-		long int val_int;
-		char *end;
-
+		/* If not given, and arp_interval is not given or disabled, default to 100 */
 		value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
-		errno = 0;
-		val_int = strtol (value ? value : "0", &end, 10);
-		if (!value || (val_int == 0 && errno == 0 && *end == '\0'))
-			set_bond_attr (device, "miimon", "100");
+		if (_nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, 0) == 0)
+			set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_MIIMON, "100");
 	}
 
-	/* The stuff after 'mode' requires the given mode or doesn't care */
-	set_bond_attr (device, "mode", mode);
-
-	/* arp_interval not compatible with ALB, TLB */
-	if (NM_IN_STRSET (mode, "balance-alb", "balance-tlb"))
-		set_arp_interval = FALSE;
-
 	if (set_arp_interval) {
-		set_simple_option (device, "arp_interval", s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
-
+		set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
 		/* Just let miimon get cleared automatically; even setting miimon to
 		 * 0 (disabled) clears arp_interval.
 		 */
 	}
 
+	/* ARP validate: value > 0 only valid in active-backup mode */
 	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE);
-	/* arp_validate > 0 only valid in active-backup mode */
 	if (   value
 	    && !nm_streq (value, "0")
 	    && !nm_streq (value, "none")
-	    && nm_streq (mode, "active-backup"))
-		set_bond_attr (device, "arp_validate", value);
+	    && mode == NM_BOND_MODE_ACTIVEBACKUP)
+		set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, value);
 	else
-		set_bond_attr (device, "arp_validate", "0");
-
-	if (NM_IN_STRSET (mode, "active-backup", "balance-alb", "balance-tlb")) {
-		value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
-		set_bond_attr (device, "primary", value ? value : "");
-		set_simple_option (device, "lp_interval", s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL);
-	}
+		set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_ARP_VALIDATE, "0");
 
-	/* Clear ARP targets */
-	contents = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, "arp_ip_target");
-	set_arp_targets (device, contents, " \n", "-");
-	g_free (contents);
+	/* Primary */
+	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
+	set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ? value : "");
 
-	/* Add new ARP targets */
+	/* ARP targets: clear and initialize the list */
+	contents = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex,
+	                                                 NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+	set_arp_targets (device, mode, contents, " \n", "-");
 	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
-	set_arp_targets (device, value, ",", "+");
-
-	set_simple_option (device, "primary_reselect", s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT);
-	set_simple_option (device, "fail_over_mac", s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC);
-	set_simple_option (device, "use_carrier", s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER);
-	set_simple_option (device, "ad_select", s_bond, NM_SETTING_BOND_OPTION_AD_SELECT);
-	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);
-	set_simple_option (device, "active_slave", s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE);
-	set_simple_option (device, "all_slaves_active", s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE);
-	set_simple_option (device, "num_grat_arp", s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP);
-	set_simple_option (device, "num_unsol_na", s_bond, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA);
-
-	if (nm_streq (mode, "802.3ad")) {
-		set_simple_option (device, "lacp_rate", s_bond, NM_SETTING_BOND_OPTION_LACP_RATE);
-		set_simple_option (device, "ad_actor_sys_prio", s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO);
-		set_simple_option (device, "ad_actor_system", s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM);
-		set_simple_option (device, "ad_user_port_key", s_bond, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY);
-		set_simple_option (device, "min_links", s_bond, NM_SETTING_BOND_OPTION_MIN_LINKS);
-	}
-
-	if (nm_streq (mode, "active-backup"))
-		set_simple_option (device, "arp_all_targets", s_bond, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS);
-
-	if (nm_streq (mode, "balance-rr"))
-		set_simple_option (device, "packets_per_slave", s_bond, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE);
+	set_arp_targets (device, mode, value, ",", "+");
+	g_free (contents);
 
-	if (nm_streq (mode, "balance-tlb"))
-		set_simple_option (device, "tlb_dynamic_lb", s_bond, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB);
+	/* AD actor system: don't set if empty */
+	value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM);
+	if (value)
+		set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM, value);
+
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_AD_SELECT);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_LACP_RATE);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_NUM_UNSOL_NA);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_MIN_LINKS);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER);
+	set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY);
 
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 }