mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-08 21:10:25 +01:00
core: do a better job of applying bond configuration
Reset all known bond options to their default values, not just the ones that NMSettingBond allows overriding. Also, remove any bond slaves that were already attached to the bond before we managed it. Only update bond parameters that need to be updated. In particular, setting either arp_interval or miimon to 0 has the side effect of also setting the other one to 0, so don't do that if it's already 0. Fix the handling of arp_ip_target; the sysfs arp_ip_target node does not work the same way as the ifcfg BONDING_OPTS line (which is what the code was assuming before).
This commit is contained in:
parent
c4994bba54
commit
49105f7115
1 changed files with 102 additions and 46 deletions
148
src/nm-system.c
148
src/nm-system.c
|
|
@ -1226,70 +1226,126 @@ nm_system_device_set_priority (int ifindex,
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_bond_attr (const char *iface, const char *attr, const char *value)
|
||||
static const struct {
|
||||
const char *option;
|
||||
const char *default_value;
|
||||
} bonding_defaults[] = {
|
||||
{ "mode", "balance-rr" },
|
||||
{ "arp_interval", "0" },
|
||||
{ "miimon", "0" },
|
||||
|
||||
{ "ad_select", "stable" },
|
||||
{ "arp_validate", "none" },
|
||||
{ "downdelay", "0" },
|
||||
{ "fail_over_mac", "none" },
|
||||
{ "lacp_rate", "slow" },
|
||||
{ "min_links", "0" },
|
||||
{ "num_grat_arp", "1" },
|
||||
{ "num_unsol_na", "1" },
|
||||
{ "primary", "" },
|
||||
{ "primary_reselect", "always" },
|
||||
{ "resend_igmp", "1" },
|
||||
{ "updelay", "0" },
|
||||
{ "use_carrier", "1" },
|
||||
{ "xmit_hash_policy", "layer2" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
remove_bonding_entries (const char *iface, const char *path)
|
||||
{
|
||||
char file[FILENAME_MAX];
|
||||
char cmd[20];
|
||||
char *value, **entries;
|
||||
gboolean ret;
|
||||
int i;
|
||||
|
||||
snprintf (file, sizeof (file), "/sys/class/net/%s/bonding/%s", iface, attr);
|
||||
ret = nm_utils_do_sysctl (file, value);
|
||||
if (!ret) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute "
|
||||
"'%s' to '%s'", iface, attr, value);
|
||||
if (!g_file_get_contents (path, &value, NULL, NULL))
|
||||
return;
|
||||
|
||||
entries = g_strsplit (value, " ", -1);
|
||||
for (i = 0; entries[i]; i++) {
|
||||
snprintf (cmd, sizeof (cmd), "-%s", g_strstrip (entries[i]));
|
||||
ret = nm_utils_do_sysctl (path, cmd);
|
||||
if (!ret) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to remove entry '%s' from '%s'",
|
||||
iface, entries[i], path);
|
||||
}
|
||||
}
|
||||
g_strfreev (entries);
|
||||
}
|
||||
|
||||
return ret;
|
||||
static gboolean
|
||||
option_valid_for_nm_setting (const char *option, const char **valid_opts)
|
||||
{
|
||||
while (*valid_opts) {
|
||||
if (strcmp (option, *valid_opts) == 0)
|
||||
return TRUE;
|
||||
valid_opts++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_system_apply_bonding_config (const char *iface, NMSettingBond *s_bond)
|
||||
{
|
||||
const char **opts, **iter;
|
||||
const char **valid_opts;
|
||||
const char *option, *value;
|
||||
char path[FILENAME_MAX];
|
||||
char *current, *space;
|
||||
gboolean ret;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (iface != NULL, FALSE);
|
||||
|
||||
/*
|
||||
* FIXME:
|
||||
*
|
||||
* ifup-eth contains code to append targets if the value is prefixed
|
||||
* with '+':
|
||||
*
|
||||
* if [ "${key}" = "arp_ip_target" -a "${value:0:1}" != "+" ]; then
|
||||
* OLDIFS=$IFS;
|
||||
* IFS=',';
|
||||
* for arp_ip in $value; do
|
||||
* if ! grep -q $arp_ip /sys/class/net/${DEVICE}/bonding/$key; then
|
||||
* echo +$arp_ip > /sys/class/net/${DEVICE}/bonding/$key
|
||||
* fi
|
||||
* done
|
||||
*
|
||||
* Not sure if this is actually being used and it seems dangerous as
|
||||
* the result is pretty much unforeseeable.
|
||||
*/
|
||||
/* Remove old slaves and arp_ip_targets */
|
||||
snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/arp_ip_target", iface);
|
||||
remove_bonding_entries (iface, path);
|
||||
snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/slaves", iface);
|
||||
remove_bonding_entries (iface, path);
|
||||
|
||||
/* Set bonding options; if the setting didn't specify a value for the
|
||||
* option then use the default value to ensure there's no leakage of
|
||||
* options from any previous connections to this one.
|
||||
*/
|
||||
opts = nm_setting_bond_get_valid_options (s_bond);
|
||||
for (iter = opts; iter && *iter; iter++) {
|
||||
const char *value;
|
||||
gboolean is_default = FALSE;
|
||||
/* Apply config/defaults */
|
||||
valid_opts = nm_setting_bond_get_valid_options (s_bond);
|
||||
for (i = 0; bonding_defaults[i].option; i++) {
|
||||
option = bonding_defaults[i].option;
|
||||
if (option_valid_for_nm_setting (option, valid_opts))
|
||||
value = nm_setting_bond_get_option_by_name (s_bond, option);
|
||||
else
|
||||
value = NULL;
|
||||
if (!value)
|
||||
value = bonding_defaults[i].default_value;
|
||||
|
||||
value = nm_setting_bond_get_option_by_name (s_bond, *iter);
|
||||
if (!value) {
|
||||
value = nm_setting_bond_get_option_default (s_bond, *iter); /* use the default value */
|
||||
is_default = TRUE;
|
||||
snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/%s", iface, option);
|
||||
if (g_file_get_contents (path, ¤t, NULL, NULL)) {
|
||||
g_strstrip (current);
|
||||
space = strchr (current, ' ');
|
||||
if (space)
|
||||
*space = '\0';
|
||||
if (strcmp (current, value) != 0) {
|
||||
ret = nm_utils_do_sysctl (path, value);
|
||||
if (!ret) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to set bonding attribute "
|
||||
"'%s' to '%s'", iface, option, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE, "(%s): setting bond option '%s' to %s'%s'",
|
||||
iface,
|
||||
*iter,
|
||||
is_default ? "default " : "",
|
||||
value);
|
||||
/* Handle arp_ip_target */
|
||||
value = nm_setting_bond_get_option_by_name (s_bond, "arp_ip_target");
|
||||
if (value) {
|
||||
char **addresses, cmd[20];
|
||||
|
||||
set_bond_attr (iface, *iter, value);
|
||||
snprintf (path, sizeof (path), "/sys/class/net/%s/bonding/arp_ip_target", iface);
|
||||
addresses = g_strsplit (value, ",", -1);
|
||||
for (i = 0; addresses[i]; i++) {
|
||||
snprintf (cmd, sizeof (cmd), "+%s", g_strstrip (addresses[i]));
|
||||
ret = nm_utils_do_sysctl (path, cmd);
|
||||
if (!ret) {
|
||||
nm_log_warn (LOGD_HW, "(%s): failed to add arp_ip_target '%s'",
|
||||
iface, addresses[i]);
|
||||
}
|
||||
}
|
||||
g_strfreev (addresses);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue