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.c215
1 files changed, 146 insertions, 69 deletions
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
index 2fedc753..71332ba3 100644
--- a/src/devices/nm-device-bond.c
+++ b/src/devices/nm-device-bond.c
@@ -8,6 +8,7 @@
 #include "nm-device-bond.h"
 
 #include <stdlib.h>
+#include <net/if.h>
 
 #include "NetworkManagerUtils.h"
 #include "nm-device-private.h"
@@ -182,7 +183,6 @@ master_update_slave_connection (NMDevice *self,
 
 static void
 set_arp_targets (NMDevice *device,
-                 NMBondMode mode,
                  const char *cur_arp_ip_target,
                  const char *new_arp_ip_target)
 {
@@ -261,15 +261,73 @@ set_bond_attr_or_default (NMDevice *device,
 	_set_bond_attr (device, opt, value);
 }
 
+static void
+set_bond_attr_active_slave (NMDevice *device, NMSettingBond *s_bond)
+{
+	NMDeviceBond *self = NM_DEVICE_BOND (device);
+	const NMPlatformLink *plink;
+	const char *value;
+	const char *error_reason;
+	int ifindex;
+
+	value = nm_setting_bond_get_option_or_default (s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE);
+	if (!value)
+		return;
+
+	if (!nm_str_is_empty (value)) {
+		ifindex = nm_device_get_ifindex (device);
+		plink = nm_platform_link_get_by_ifname (nm_device_get_platform (device), value);
+		if (!plink)
+			error_reason = "does not exist";
+		else if (plink->master != ifindex)
+			error_reason = "is not yet enslaved";
+		else if (!NM_FLAGS_HAS (plink->n_ifi_flags, IFF_UP))
+			error_reason = "is not up";
+		else
+			error_reason = NULL;
+
+		if (error_reason) {
+			_LOGT (LOGD_BOND, "bond option 'active_slave' not set as device \"%s\" %s", value, error_reason);
+			return;
+		}
+	}
+
+	_set_bond_attr (device, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE, value);
+}
+
+static void
+set_bond_attrs_or_default (NMDevice *device, NMSettingBond *s_bond, const char *const *attr_v)
+{
+	nm_assert (NM_IS_DEVICE (device));
+	nm_assert (s_bond);
+	nm_assert (attr_v);
+
+	for ( ; *attr_v ; ++attr_v)
+		set_bond_attr_or_default (device, s_bond, *attr_v);
+}
+
+static void
+set_bond_arp_ip_targets (NMDevice *device, NMSettingBond *s_bond)
+{
+	int           ifindex           = nm_device_get_ifindex (device);
+	gs_free char *cur_arp_ip_target = NULL;
+
+	/* ARP targets: clear and initialize the list */
+	cur_arp_ip_target = nm_platform_sysctl_master_get_option (nm_device_get_platform (device),
+	                                                          ifindex,
+	                                                          NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+	set_arp_targets (device,
+	                 cur_arp_ip_target,
+	                 nm_setting_bond_get_option_or_default (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET));
+}
+
 static gboolean
 apply_bonding_config (NMDeviceBond *self)
 {
 	NMDevice *device = NM_DEVICE (self);
-	int ifindex = nm_device_get_ifindex (device);
 	NMSettingBond *s_bond;
 	NMBondMode mode;
 	const char *mode_str;
-	gs_free char *cur_arp_ip_target = NULL;
 
 	s_bond = nm_device_get_applied_setting (device, NM_TYPE_SETTING_BOND);
 	g_return_val_if_fail (s_bond, FALSE);
@@ -283,40 +341,34 @@ apply_bonding_config (NMDeviceBond *self)
 	 */
 	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_MODE);
 
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_MIIMON);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_UPDELAY);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_ARP_VALIDATE);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
-
-	/* ARP targets: clear and initialize the list */
-	cur_arp_ip_target = nm_platform_sysctl_master_get_option (nm_device_get_platform (device),
-	                                                          ifindex,
-	                                                          NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
-	set_arp_targets (device,
-	                 mode,
-	                 cur_arp_ip_target,
-	                 nm_setting_bond_get_option_or_default (s_bond, NM_SETTING_BOND_OPTION_ARP_IP_TARGET));
-
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_AD_SELECT);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_FAIL_OVER_MAC);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_LACP_RATE);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_LP_INTERVAL);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_MIN_LINKS);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_PRIMARY_RESELECT);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_RESEND_IGMP);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_USE_CARRIER);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY);
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_NUM_GRAT_ARP);
+	set_bond_arp_ip_targets (device, s_bond);
+	set_bond_attr_active_slave (device, s_bond);
+
+	set_bond_attrs_or_default (device,
+	                           s_bond,
+	                           NM_MAKE_STRV (NM_SETTING_BOND_OPTION_MIIMON,
+	                                         NM_SETTING_BOND_OPTION_UPDELAY,
+	                                         NM_SETTING_BOND_OPTION_DOWNDELAY,
+	                                         NM_SETTING_BOND_OPTION_ARP_INTERVAL,
+	                                         NM_SETTING_BOND_OPTION_ARP_VALIDATE,
+	                                         NM_SETTING_BOND_OPTION_PRIMARY,
+	                                         NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM,
+	                                         NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO,
+	                                         NM_SETTING_BOND_OPTION_AD_SELECT,
+	                                         NM_SETTING_BOND_OPTION_AD_USER_PORT_KEY,
+	                                         NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE,
+	                                         NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS,
+	                                         NM_SETTING_BOND_OPTION_FAIL_OVER_MAC,
+	                                         NM_SETTING_BOND_OPTION_LACP_RATE,
+	                                         NM_SETTING_BOND_OPTION_LP_INTERVAL,
+	                                         NM_SETTING_BOND_OPTION_MIN_LINKS,
+	                                         NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE,
+	                                         NM_SETTING_BOND_OPTION_PRIMARY_RESELECT,
+	                                         NM_SETTING_BOND_OPTION_RESEND_IGMP,
+	                                         NM_SETTING_BOND_OPTION_TLB_DYNAMIC_LB,
+	                                         NM_SETTING_BOND_OPTION_USE_CARRIER,
+	                                         NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY,
+	                                         NM_SETTING_BOND_OPTION_NUM_GRAT_ARP));
 	return TRUE;
 }
 
@@ -378,7 +430,7 @@ enslave_slave (NMDevice *device,
 				if (nm_streq0 (active, nm_device_get_iface (slave))) {
 					nm_platform_sysctl_master_set_option (nm_device_get_platform (device),
 					                                      nm_device_get_ifindex (device),
-					                                      "active_slave",
+					                                      NM_SETTING_BOND_OPTION_ACTIVE_SLAVE,
 					                                      active);
 					_LOGD (LOGD_BOND, "setting slave %s as active one for master %s",
 					       active, nm_device_get_iface (device));
@@ -481,31 +533,41 @@ create_and_realize (NMDevice *device,
 static gboolean
 check_changed_options (NMSettingBond *s_a, NMSettingBond *s_b, GError **error)
 {
-	guint i, num;
-	const char *name = NULL, *value_a = NULL, *value_b = NULL;
+	const char **option_list;
 
-	/* Check that options in @s_a have compatible changes in @s_b */
+	option_list = nm_setting_bond_get_valid_options (NULL);
 
-	num = nm_setting_bond_get_num_options (s_a);
-	for (i = 0; i < num; i++) {
-		nm_setting_bond_get_option (s_a, i, &name, &value_a);
+	for (; *option_list; ++option_list) {
+		const char *name = *option_list;
 
 		/* We support changes to these */
 		if (NM_IN_STRSET (name,
-		                  NM_SETTING_BOND_OPTION_ACTIVE_SLAVE,
-		                  NM_SETTING_BOND_OPTION_PRIMARY)) {
-			continue;
-		}
-
-		/* Missing in @s_b, but has a default value in @s_a */
-		value_b = nm_setting_bond_get_option_by_name (s_b, name);
-		if (   !value_b
-		    && nm_streq0 (value_a, nm_setting_bond_get_option_default (s_a, name))) {
+		                  NM_SETTING_BOND_OPTION_PRIMARY,
+		                  NM_SETTING_BOND_OPTION_MIIMON,
+		                  NM_SETTING_BOND_OPTION_UPDELAY,
+		                  NM_SETTING_BOND_OPTION_DOWNDELAY,
+		                  NM_SETTING_BOND_OPTION_ARP_INTERVAL,
+		                  NM_SETTING_BOND_OPTION_ARP_VALIDATE,
+		                  NM_SETTING_BOND_OPTION_PRIMARY,
+		                  NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM,
+		                  NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO,
+		                  NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE,
+		                  NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS,
+		                  NM_SETTING_BOND_OPTION_FAIL_OVER_MAC,
+		                  NM_SETTING_BOND_OPTION_LP_INTERVAL,
+		                  NM_SETTING_BOND_OPTION_MIN_LINKS,
+		                  NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE,
+		                  NM_SETTING_BOND_OPTION_PRIMARY_RESELECT,
+		                  NM_SETTING_BOND_OPTION_RESEND_IGMP,
+		                  NM_SETTING_BOND_OPTION_USE_CARRIER,
+		                  NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY,
+		                  NM_SETTING_BOND_OPTION_NUM_GRAT_ARP)) {
 			continue;
 		}
 
 		/* Reject any other changes */
-		if (!nm_streq0 (value_a, value_b)) {
+		if (!nm_streq0 (nm_setting_bond_get_option_normalized (s_a, name),
+		                nm_setting_bond_get_option_normalized (s_b, name))) {
 			g_set_error (error,
 			             NM_DEVICE_ERROR,
 			             NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
@@ -527,7 +589,6 @@ can_reapply_change (NMDevice *device,
                     GError **error)
 {
 	NMDeviceClass *device_class;
-	NMSettingBond *s_bond_old, *s_bond_new;
 
 	/* Only handle bond setting here, delegate other settings to parent class */
 	if (nm_streq (setting_name, NM_SETTING_BOND_SETTING_NAME)) {
@@ -537,15 +598,7 @@ can_reapply_change (NMDevice *device,
 		                                        NM_SETTING_BOND_OPTIONS))
 			return FALSE;
 
-		s_bond_old = NM_SETTING_BOND (s_old);
-		s_bond_new = NM_SETTING_BOND (s_new);
-
-		if (   !check_changed_options (s_bond_old, s_bond_new, error)
-		    || !check_changed_options (s_bond_new, s_bond_old, error)) {
-			return FALSE;
-		}
-
-		return TRUE;
+		return check_changed_options (NM_SETTING_BOND (s_old), NM_SETTING_BOND (s_new), error);
 	}
 
 	device_class = NM_DEVICE_CLASS (nm_device_bond_parent_class);
@@ -561,8 +614,8 @@ static void
 reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_new)
 {
 	NMDeviceBond *self = NM_DEVICE_BOND (device);
-	const char *value;
 	NMSettingBond *s_bond;
+	const char *value;
 	NMBondMode mode;
 
 	NM_DEVICE_CLASS (nm_device_bond_parent_class)->reapply_connection (device,
@@ -577,10 +630,34 @@ reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_n
 	mode = _nm_setting_bond_mode_from_string (value);
 	g_return_if_fail (mode != NM_BOND_MODE_UNKNOWN);
 
-	/* Primary */
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_PRIMARY);
-	/* Active slave */
-	set_bond_attr_or_default (device, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE);
+	/* Below we set only the bond options that kernel allows to modify
+	 * while keeping the bond interface up */
+
+	set_bond_attr_active_slave (device, s_bond);
+	set_bond_arp_ip_targets (device, s_bond);
+
+	set_bond_attrs_or_default (device,
+	                           s_bond,
+	                           NM_MAKE_STRV (NM_SETTING_BOND_OPTION_PRIMARY,
+	                                         NM_SETTING_BOND_OPTION_MIIMON,
+	                                         NM_SETTING_BOND_OPTION_UPDELAY,
+	                                         NM_SETTING_BOND_OPTION_DOWNDELAY,
+	                                         NM_SETTING_BOND_OPTION_ARP_INTERVAL,
+	                                         NM_SETTING_BOND_OPTION_ARP_VALIDATE,
+	                                         NM_SETTING_BOND_OPTION_PRIMARY,
+	                                         NM_SETTING_BOND_OPTION_AD_ACTOR_SYSTEM,
+	                                         NM_SETTING_BOND_OPTION_AD_ACTOR_SYS_PRIO,
+	                                         NM_SETTING_BOND_OPTION_ALL_SLAVES_ACTIVE,
+	                                         NM_SETTING_BOND_OPTION_ARP_ALL_TARGETS,
+	                                         NM_SETTING_BOND_OPTION_FAIL_OVER_MAC,
+	                                         NM_SETTING_BOND_OPTION_LP_INTERVAL,
+	                                         NM_SETTING_BOND_OPTION_MIN_LINKS,
+	                                         NM_SETTING_BOND_OPTION_PACKETS_PER_SLAVE,
+	                                         NM_SETTING_BOND_OPTION_PRIMARY_RESELECT,
+	                                         NM_SETTING_BOND_OPTION_RESEND_IGMP,
+	                                         NM_SETTING_BOND_OPTION_USE_CARRIER,
+	                                         NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY,
+	                                         NM_SETTING_BOND_OPTION_NUM_GRAT_ARP));
 }
 
 /*****************************************************************************/