diff options
| author | Michael Biebl <biebl@debian.org> | 2017-05-11 14:55:55 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2017-05-11 14:55:55 +0200 |
| commit | c333f062ddcba9b35330647bf6cbd0a07f2d786e (patch) | |
| tree | 257c3a0c74c09f4ad2328eab5b932806405f0c1c /src/devices/nm-device-bond.c | |
| parent | a222e56e103f949b148a6942e385ccca2c26d9f3 (diff) | |
New upstream version 1.8.0 upstream/1.8.0
Diffstat (limited to 'src/devices/nm-device-bond.c')
| -rw-r--r-- | src/devices/nm-device-bond.c | 156 |
1 files changed, 143 insertions, 13 deletions
diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index 34d34eb4..3325c948 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -101,7 +101,7 @@ complete_connection (NMDevice *device, { NMSettingBond *s_bond; - nm_utils_complete_generic (NM_PLATFORM_GET, + nm_utils_complete_generic (nm_device_get_platform (device), connection, NM_SETTING_BOND_SETTING_NAME, existing_connections, @@ -131,7 +131,7 @@ set_bond_attr (NMDevice *device, NMBondMode mode, const char *attr, const char * if (!_nm_setting_bond_option_supported (attr, mode)) return FALSE; - ret = nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, attr, value); + ret = nm_platform_sysctl_master_set_option (nm_device_get_platform (device), ifindex, attr, value); if (!ret) _LOGW (LOGD_PLATFORM, "failed to set bonding attribute '%s' to '%s'", attr, value); return ret; @@ -165,7 +165,7 @@ update_connection (NMDevice *device, NMConnection *connection) /* Read bond options from sysfs and update the Bond setting to match */ options = nm_setting_bond_get_valid_options (s_bond); while (options && *options) { - gs_free char *value = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, *options); + gs_free char *value = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), ifindex, *options); const char *defvalue = nm_setting_bond_get_option_default (s_bond, *options); char *p; @@ -328,7 +328,7 @@ apply_bonding_config (NMDevice *device) set_bond_attr (device, mode, NM_SETTING_BOND_OPTION_PRIMARY, value ? value : ""); /* ARP targets: clear and initialize the list */ - contents = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, + contents = nm_platform_sysctl_master_get_option (nm_device_get_platform (device), 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); @@ -363,21 +363,19 @@ apply_bonding_config (NMDevice *device) } static NMActStageReturn -act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *out_failure_reason) { NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; gboolean no_firmware = FALSE; - g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - - ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, reason); + ret = NM_DEVICE_CLASS (nm_device_bond_parent_class)->act_stage1_prepare (dev, out_failure_reason); if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; /* Interface must be down to set bond options */ nm_device_take_down (dev, TRUE); ret = apply_bonding_config (dev); - if (ret) + if (ret != NM_ACT_STAGE_RETURN_FAILURE) ret = nm_device_hw_addr_set_cloned (dev, nm_device_get_applied_connection (dev), FALSE); nm_device_bring_up (dev, TRUE, &no_firmware); @@ -393,12 +391,13 @@ enslave_slave (NMDevice *device, NMDeviceBond *self = NM_DEVICE_BOND (device); gboolean success = TRUE, no_firmware = FALSE; const char *slave_iface = nm_device_get_ip_iface (slave); + NMConnection *master_con; nm_device_master_check_slave_physical_port (device, slave, LOGD_BOND); if (configure) { nm_device_take_down (slave, TRUE); - success = nm_platform_link_enslave (NM_PLATFORM_GET, + success = nm_platform_link_enslave (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)); nm_device_bring_up (slave, TRUE, &no_firmware); @@ -407,6 +406,25 @@ enslave_slave (NMDevice *device, return FALSE; _LOGI (LOGD_BOND, "enslaved bond slave %s", slave_iface); + + /* The active_slave option can be set only after the interface is enslaved */ + master_con = nm_device_get_applied_connection (device); + if (master_con) { + NMSettingBond *s_bond = nm_connection_get_setting_bond (master_con); + const char *active; + + if (s_bond) { + active = nm_setting_bond_get_option_by_name (s_bond, "active_slave"); + if (active && 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", + active); + _LOGD (LOGD_BOND, "setting slave %s as active one for master %s", + active, nm_device_get_iface (device)); + } + } + } } else _LOGI (LOGD_BOND, "bond slave %s was enslaved", slave_iface); @@ -428,7 +446,7 @@ release_slave (NMDevice *device, */ address = g_strdup (nm_device_get_hw_address (device)); - success = nm_platform_link_release (NM_PLATFORM_GET, + success = nm_platform_link_release (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), nm_device_get_ip_ifindex (slave)); @@ -440,7 +458,7 @@ release_slave (NMDevice *device, nm_device_get_ip_iface (slave)); } - nm_platform_process_events (NM_PLATFORM_GET); + nm_platform_process_events (nm_device_get_platform (device)); if (nm_device_update_hw_address (device)) nm_device_hw_addr_set (device, address, "restore", FALSE); @@ -468,7 +486,7 @@ create_and_realize (NMDevice *device, g_assert (iface); - plerr = nm_platform_link_bond_add (NM_PLATFORM_GET, iface, out_plink); + plerr = nm_platform_link_bond_add (nm_device_get_platform (device), iface, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create bond interface '%s' for '%s': %s", @@ -480,6 +498,116 @@ create_and_realize (NMDevice *device, return TRUE; } +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; + + /* Check that options in @s_a have compatible changes in @s_b */ + + 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); + + /* 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))) { + continue; + } + + /* Reject any other changes */ + if (!nm_streq0 (value_a, value_b)) { + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + "Can't reapply '%s' bond option", + name); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +can_reapply_change (NMDevice *device, + const char *setting_name, + NMSetting *s_old, + NMSetting *s_new, + GHashTable *diffs, + 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)) { + if (!nm_device_hash_check_invalid_keys (diffs, + NM_SETTING_BOND_SETTING_NAME, + error, + 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; + } + + device_class = NM_DEVICE_CLASS (nm_device_bond_parent_class); + return device_class->can_reapply_change (device, + setting_name, + s_old, + s_new, + diffs, + error); +} + +static void +reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_new) +{ + NMDeviceBond *self = NM_DEVICE_BOND (device); + const char *value; + NMSettingBond *s_bond; + NMBondMode mode; + + NM_DEVICE_CLASS (nm_device_bond_parent_class)->reapply_connection (device, + con_old, + con_new); + + _LOGD (LOGD_BOND, "reapplying bond settings"); + s_bond = nm_connection_get_setting_bond (con_new); + g_return_if_fail (s_bond); + + value = nm_setting_bond_get_option_by_name (s_bond, NM_SETTING_BOND_OPTION_MODE); + if (!value) + value = "balance-rr"; + + mode = _nm_setting_bond_mode_from_string (value); + g_return_if_fail (mode != NM_BOND_MODE_UNKNOWN); + + /* 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 : ""); + + /* Active slave */ + set_simple_option (device, mode, s_bond, NM_SETTING_BOND_OPTION_ACTIVE_SLAVE); +} + /*****************************************************************************/ static void @@ -508,6 +636,8 @@ nm_device_bond_class_init (NMDeviceBondClass *klass) parent_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; + parent_class->can_reapply_change = can_reapply_change; + parent_class->reapply_connection = reapply_connection; nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), NMDBUS_TYPE_DEVICE_BOND_SKELETON, |